VBScriptを極める:BOM検知による文字コード自動判別とADODB.Streamの深淵
業務自動化の現場において、「テキストファイルの読み込み」は最も軽視され、かつ最も地雷が埋まっている工程だ。多くのエンジニアが`Scripting.FileSystemObject (FSO)`の`.OpenTextFile`に安易に手を出すが、あれは「ASCIIまたはシステム規定のコードページ」という現代ではあまりに無力な制約の上に成り立っている。
UTF-8のBOMあり/なし、UTF-16 LE/BE、そして日本の現場に呪いのように残るShift-JIS。これらを「手動で設定を変える」ような運用は、自動化の定義を根本から否定している。
今日は、プロとして恥ずかしくない、バイナリ解析による完全自動判別エンジンの実装を伝授する。
—
なぜFSO単体では「死」を迎えるのか
FSOの`OpenTextFile`メソッドは、ファイルを開く際に文字コードを固定で要求する。UTF-8(特にBOMなし)を指定しようものなら、日本語は即座に文字化けし、処理は破綻する。
我々が取るべき戦略は一つ。「先頭バイトによるバイナリ判別」と「ADODB.Streamによるバッファ制御」の融合だ。
文字コード判別の鉄則:BOMのシグネチャ
ファイル冒頭の数バイトを読み取り、以下のシグネチャを特定する。
| エンコーディング | シグネチャ (Hex) |
| :— | :— |
| UTF-8 (BOMあり) | EF BB BF |
| UTF-16 LE | FF FE |
| UTF-16 BE | FE FF |
| Shift-JIS / その他 | (上記以外) |
—
実装:堅牢な自動判別ライブラリ
以下のコードは、単なるコピペコードではない。オブジェクトの解放(`Nothing`代入)を徹底し、メモリリークを許さないプロダクション品質の設計だ。
‘ — 自動判別・読み込みライブラリ —
Function ReadFileAuto(strFilePath)
Dim adoStream, objFSO, fileStream
Dim binHeader, strCharset
Set adoStream = CreateObject(“ADODB.Stream”)
‘ 1. バイナリモードで先頭3バイトを取得
adoStream.Type = 1 ‘ adTypeBinary
adoStream.Open
adoStream.LoadFromFile strFilePath
binHeader = adoStream.Read(3)
adoStream.Close
‘ 2. BOM解析による文字コード特定
‘ ※バイナリ値の比較はAscB関数を使用する
If AscB(MidB(binHeader, 1, 1)) = &HEF And AscB(MidB(binHeader, 2, 1)) = &HBB And AscB(MidB(binHeader, 3, 1)) = &HBF Then
strCharset = “UTF-8”
ElseIf AscB(MidB(binHeader, 1, 1)) = &HFF And AscB(MidB(binHeader, 2, 1)) = &HFE Then
strCharset = “UTF-16”
ElseIf AscB(MidB(binHeader, 1, 1)) = &HFE And AscB(MidB(binHeader, 2, 1)) = &HFF Then
strCharset = “unicodeFFFE” ‘ UTF-16BE
Else
strCharset = “Shift-JIS” ‘ デフォルトの逃げ道
End If
‘ 3. 特定したコードでテキストとして読み込み
adoStream.Type = 2 ‘ adTypeText
adoStream.Charset = strCharset
adoStream.Open
adoStream.LoadFromFile strFilePath
ReadFileAuto = adoStream.ReadText
‘ 後始末の徹底:VBScriptでは必須の儀式
adoStream.Close
Set adoStream = Nothing
End Function
—
プロフェッショナルのための設計思想
1. なぜStreamを使うのか?
FSOはファイルシステムへのアクセスには優れているが、「文字ストリームの変換」に関してはADODB.Streamに遠く及ばない。ADODB.StreamはOSレベルでUnicode変換をサポートしており、メモリ効率と変換精度が段違いだ。
2. 「Shift-JIS」という地雷
上記のコードでデフォルトを`Shift-JIS`としているのは、日本のレガシーシステムとの互換性を考慮した現実的な妥協だ。しかし、もし業務要件が「UTF-8(BOMなし)前提」であるならば、`ADODB.Stream`で読み込んだ後に正規表現などで文字化け検知ロジックを挟む、あるいは`UTF-8`を強制適用する設計へ拡張する必要がある。
3. パフォーマンスの罠
このコードは小〜中規模のテキストファイルを対象にしている。もし数GB単位のログファイルを扱う場合、`ReadText`で全量をメモリに乗せるのは自殺行為だ。その場合は、`ReadText(Line)`をループさせ、ストリームを逐次消費する設計に切り替える必要がある。
—
現場で成果を出すために
自動化ツールは「動く」だけでは不十分だ。「予期せぬ入力に対しても、例外を投げて静かに停止する」ことが、運用保守のコストを最小化する。
- エラーハンドリング: `On Error Resume Next`を多用せず、`adoStream.LoadFromFile`の前には必ず`FSO.FileExists`でファイルの存在を確認せよ。
- 権限の考慮: Webサーバーやタスクスケジューラで動かす場合、ADODB.Streamが一時ファイルを作成する権限があるかを確認しておくこと。
このライブラリをあなたのツールボックスに加えれば、もう文字コードごときで深夜のトラブルシューティングに追われることはないはずだ。コードは、書く者の知性を反映する。美しく、堅牢に実装してくれ。
