VBScriptの深淵:FileSystemObjectで「全角・半角混在」を安全に捌く極意
現場の自動化ツールで最も「見えない地雷」を踏みやすい場所はどこか? それは、FSO(FileSystemObject)を通じたテキストの読み込み処理だ。
多くのエンジニアが `TextStream.ReadAll` や `ReadLine` で安易にファイルを開き、`Len` や `Mid` で文字列を切り出そうとして、全角文字のバイト長と文字数の乖離によってシステムをクラッシュさせる。
VBScriptは、内部的にはUnicodeで文字列を扱うが、ファイル操作においてはOSのコードページや文字コードの壁が常に立ちはだかる。今日は、この「バイトと文字のギャップ」を完全に制圧するための、プロダクションレベルの「SafeRead」術を伝授する。
—
1. なぜ「その読み込み」では危険なのか?
VBScriptの `Len()` 関数は「文字数」を返し、`LenB()` は「バイト数」を返す。しかし、FSOの `TextStream` は、デフォルト(ASCII/ANSI)で読み込む際、マルチバイト文字(Shift-JIS等の全角)を「1文字=2バイト」として扱う場面と、文字としてカウントする場面が混在し、制御が極めて不安定になる。
特に、固定長ファイル(CSVやDAT)を位置指定で読み込む際、全角文字が含まれていると `Mid()` による切り出しで致命的なオフセットズレが発生し、データが化ける。これが「なぜか特定のファイルだけでエラーになる」という、デバッグ泣かせのバグの正体だ。
—
2. 結論:ADODB.Streamを「真の読み込み」として採用せよ
FSOの `OpenTextFile` は、小規模なログ出力には向くが、エンコーディングの制御が甘い。文字コードを明示的に指定し、メモリ上に正確にロードするには、`ADODB.Stream` オブジェクトを介するのが、この世界における唯一の「正解」だ。
実践:堅牢な SafeRead 実装コード
以下のコードは、文字コード(Shift-JISやUTF-8)を明示し、全角・半角混在環境でも位置ズレを起こさない、実務でそのまま使えるテンプレートだ。
‘ — Function: SafeReadFile —
‘ @param filePath ファイルパス
‘ @param charset 文字コード (例: “shift_jis”, “utf-8”)
‘ @return 読み込まれた文字列
Function SafeReadFile(filePath, charset)
Dim objStream
Set objStream = CreateObject(“ADODB.Stream”)
‘ ストリームの初期設定
objStream.Type = 2 ‘ adTypeText
objStream.Charset = charset
‘ ファイルを開き、全内容を読み込む
On Error Resume Next
objStream.Open
objStream.LoadFromFile filePath
If Err.Number <> 0 Then
‘ エラーハンドリング:ファイルが存在しない、または権限がない場合
SafeReadFile = “”
Err.Clear
Else
SafeReadFile = objStream.ReadText
End If
On Error GoTo 0
objStream.Close
Set objStream = Nothing
End Function
‘ — 利用例:全角混在データを安全に処理する —
Dim content, targetLine
content = SafeReadFile(“C:\data\input.txt”, “shift_jis”)
‘ ファイル内の各行を処理
Dim lines, i
lines = Split(content, vbCrLf)
For i = 0 To UBound(lines)
‘ 文字数ベースで安全に切り出す
‘ 従来型のMid/Lenではなく、ADODBで読み込んだ文字列は
‘ VBScriptのUnicode管理下にあるため、Midで正確に文字単位で操作可能
If Len(lines(i)) > 10 Then
WScript.Echo Mid(lines(i), 1, 10)
End If
Next
—
3. なぜこの設計が「最強」なのか?
1. エンコーディングの強制: `ADODB.Stream` を使うことで、ファイルシステムが勝手に解釈する「環境依存のコードページ」を排除できる。これにより、UTF-8やShift-JISといった文字コードを完全に制御下に置く。
2. Unicodeへの変換: `LoadFromFile` 時点ですべての文字がVBScript内部のUnicode(UTF-16)に変換される。これにより、`Mid()` や `Len()` 関数が本来の「文字数」として機能するようになり、バイト数と文字数の計算に悩む必要がなくなる。
3. メモリ効率とライフサイクル: `Set objStream = Nothing` を明示的に呼び出すことで、リソースリークを防ぐ。VBScriptのガベージコレクションは頼りにならない。リソースは自ら使い、自ら閉じる。これがプロの流儀だ。
—
4. 最後に:現場のエンジニアへ送るメッセージ
「とりあえず `OpenTextFile`」という実装は、数千件程度のデータなら動く。しかし、あなたのツールが運用保守に入り、誰かが全角スペースを含んだデータや、未知の文字コードのファイルを流し込んだ瞬間、そのツールは沈黙する。
「文字コードを意識し、メモリへロードする責任を持つこと」。
この視点を持つだけで、あなたの書く自動化スクリプトの信頼性は劇的に向上する。バグを後から直すな。バグが入り込む余地のないアーキテクチャを、最初から設計せよ。それが、伝説の自動化エンジニアとしての第一歩だ。
