【入門編】VB.NETにおけるChar型とString型の境界線:文字コード(Unicode/Shift_JIS)の差異で文字化けを起こさない文字列処理 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

こんにちは!現場の最前線でコードと格闘するあなたの背中をそっと押す、シニア・アーキテクトです。

今回は、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が要求する「バイト数」は違うことを忘れない。

ここをマスターしたあなたなら、レガシーシステムとの連携も、モダンなテキスト処理も思いのままです。自信を持って、次のコードを書いていきましょう!

タイトルとURLをコピーしました