こんにちは!現場の最前線でコードと格闘するあなたの背中をそっと押す、シニア・アーキテクトです。
今回は、VB.NETプログラミングにおいて、誰もが一度はハマる「Char型とString型の境界線」、そして外部システム連携の鬼門である「文字コード(UnicodeとShift_JIS)の罠」について徹底解説します。
「文字化けが起きる原因が分からない」「ダブルクォートとシングルクォートの使い分けでモヤモヤする」……そんな悩みを抱えていませんか?ここをクリアすれば、あなたもう「マクロの記録」を卒業した本物の.NETエンジニアです。さあ、一緒に本質の扉を開きましょう!
—
1. 文字の最小単位:Char型とString型の本質的違い
まずは、VB.NETの基本中の基本である「文字」の入れ物について整理します。ここをあやふやにしていると、コンパイラから冷たいエラーを突きつけられることになります。
- `Char` 型(1文字): システム内部で16ビット(2バイト)のUnicode文字を1つだけ格納します。
- `String` 型(文字列): 0文字以上の `Char` 型が鎖のように繋がった「参照型」のオブジェクトです。
データの重みを知る:シングルクォート ( `’` ) と ダブルクォート ( `”` )
VB.NETでは、ここで使う「クォート」の種類でデータ型が決定されます。
Dim c As Char = “A”C ‘ 【Char型】 末尾の ‘C’(またはOption Strict On)でCharと明示
Dim s As String = “A” ‘ 【String型】 ダブルクォートで囲むと文字列(String)になる
> ★先輩からの知恵袋
> `Option Strict On`(厳格モード)が有効なモダンなVB.NET環境では、シングルクォートで囲んだ文字リテラル(例: `’A’`)は自動的に `Char` 型になりますが、ダブルクォートで囲むと自動的に `String` 型になります。これを混ぜて使うとコンパイルエラーになるため、「1文字ならChar、文章ならString」と厳格に使い分けましょう。
—
2. なぜ文字化けは起きるのか?(Unicode vs Shift_JIS)
VB.NETの世界(内部メモリ)は、基本的にすべて UTF-16(Unicode) で世界中の文字を優しく包み込んでいます。しかし、一歩外に出て「レガシーなCSVファイル」や「古い外部API」と通信した瞬間、悲劇が起きます。
日本のビジネス現場でいまだに根強い Shift_JIS(CP932) などの文字コードの世界へ、VB.NETの温室育ちの文字列をそのまま放り込むと……
- 「①」「㈱」「髙」などの環境依存文字や機種依存文字が `?` に化ける
- 文字数のカウントがズレてパース(解析)に失敗する
これが文字化けの正体です。「メモリの中(Unicode)」と「外の世界(Shift_JIS等)」の翻訳機として働くのが、`System.Text.Encoding` クラスなのです。
—
3. 【実践】文字化けを防ぐ!正しいファイルの読み書き
百聞は一見にしかず。Shift_JISで保存された古いテキストファイルを、VB.NETで文字化けさせずに安全に読み書きする実用コードを見てみましょう。
Imports System.IO
Imports System.Text
Module TextProcessingMaster
Sub Main()
‘ 1. Shift_JISの文字コードを明示的に取得する(ここが命綱!)
‘ ※ 日本語Windows環境のレガシーファイルには Encoding.GetEncoding(932) が必須
Dim shiftJis As Encoding = Encoding.GetEncoding(“Shift_JIS”)
Dim filePath As String = “C:\Data\legacy_data.csv”
Try
‘ —【読み込み編】文字化けを絶対に許さない StreamReader —
‘ 第2引数に shiftJis を渡すことで、内部のUTF-16へ正しく翻訳して読み込みます
Using reader As New StreamReader(filePath, shiftJis)
Dim line As String
‘ 1行ずつ安全に読み込む
While Not reader.EndOfStream
line = reader.ReadLine()
‘ ここでString型として安全に処理できる
Console.WriteLine(“読み込みデータ: ” & line)
End While
End Using
‘ —【書き込み編】Shift_JIS形式で外の世界へ出力する StreamWriter —
Dim outputFilePath As String = “C:\Data\output_data.csv”
‘ 第2引数に False(上書き), 第3引数に shiftJis を指定
Using writer As New StreamWriter(outputFilePath, False, shiftJis)
writer.WriteLine(“ID,名前,備考”)
writer.WriteLine(“1,山田太郎,特殊文字なし”)
End Using
Console.WriteLine(“ファイルの入出力処理が正常に完了しました。”)
Catch ex As Exception
Console.WriteLine(“エラー発生: ” & ex.Message)
End Try
End Sub
End Module
コードの解説とアーキテクトの視点
1. `Encoding.GetEncoding(“Shift_JIS”)` (または `932`):
OSのデフォルト設定(環境によって変わる日和見な設定)に頼らず、コード側で「私はShift_JISを扱うんだ」と明示するのがプロの鉄則です。
2. `Using` ステートメントの活用:
ファイルやネットワークストリームなどの非管理リソースは、メモリを圧迫します。`Using` を使うことで、処理が終わった瞬間に確実にメモリ解放(Dispose)が行われます。オブジェクトのライフサイクルをコントロールできるエンジニアは信頼されます。
—
4. ありがちな罠:Len関数とLengthプロパティの勘違い
最後に、文字コードやString型を扱う上で初心者が踏みがちなしこたま痛い罠をご紹介します。
VB.NET(.NET Framework / .NET Core)の `String.Length` は、「Char(16ビット)の数」を返します。
しかし、サロゲートペア(絵文字や一部の特殊漢字など、2つのCharで1文字を表現する文字)が含まれている場合、文字数とLengthの数が一致しません。
また、バイト数(データ量)を知りたい場合は、先ほどの `Encoding` を使って計算する必要があります。
Dim text As String = “あいうえお”
‘ バイト数を厳密に取得したい場合(Shift_JISでのサイズ)
Dim sjisByteCount As Integer = Encoding.GetEncoding(“Shift_JIS”).GetByteCount(text)
Console.WriteLine(“文字数: ” & text.Length) ) ‘ 5
Console.WriteLine(“Shift_JISのバイト数: ” & sjisByteCount) ‘ 10 (1文字2バイト×5)
データベースの文字数制限(例:VARCHAR(10)など)にデータを突っ込む際、文字数(Length)だけで判定してデータベース側で切り捨てエラー(Truncation Error)を起こすトラブルは、現場で後を絶ちません。「文字数」と「バイト数」は別物であるという意識を常に持ちましょう。
—
まとめ:ここをクリアすれば基本はバッチリ!
- Char型は1文字(シングルクォート)、String型は文字列(ダブルクォート)の器。
- 外部のテキストファイルを扱うときは、OS任せにせず `System.Text.Encoding.GetEncoding(“Shift_JIS”)` を明示して文字化けを防ぐ。
- ファイルを開いたら `Using` で確実に閉じ、オブジェクトのライフサイクルを守る。
- 画面上の「文字数」と、ファイルやDBが要求する「バイト数」は違うことを忘れない。
ここをマスターしたあなたなら、レガシーシステムとの連携も、モダンなテキスト処理も思いのままです。自信を持って、次のコードを書いていきましょう!
