VBScriptで「BOMなしUTF-8」を制する:ADODB.Streamによる究極のファイル結合術
こんにちは。自動化の現場でVBScriptと長年向き合ってきたエンジニアです。
皆さんは、複数のテキストファイルを結合しようとして、「なぜか文字化けする」「結合したファイルの先頭にゴミのような記号(BOM)が入り込む」といった壁にぶつかったことはありませんか?
VBScriptの標準的な `FileSystemObject` は、残念ながら「BOMなしUTF-8」の繊細な取り扱いが苦手です。しかし、Windowsに標準搭載された `ADODB.Stream` オブジェクトを使いこなせば、バイナリレベルで制御することで、どんな巨大なテキストファイルも正確に、かつ安全に結合できます。
今日は、プロの現場で即戦力となる「BOM破壊を抑止するファイル結合」の極意をお伝えします。
—
なぜ「BOM」が邪魔をするのか?
まず、敵を知りましょう。
UTF-8ファイルには、先頭に「これはUTF-8ですよ」と示すためのBOM(Byte Order Mark)という3バイトの信号が付与されることがあります。
もし、BOM付きのファイルを複数つなげるとどうなるか。
結合先のファイルの「真ん中」にBOMが紛れ込み、システムがそれを「未知の文字」として誤認し、文字化けやプログラムの読み込みエラーを引き起こします。
我々の目的は、「結合したファイルの先頭にはBOMを許し、それ以降のファイルからはBOMを剥ぎ取る」こと。これを実現するのが `ADODB.Stream` です。
—
実践コード:BOMを制御して安全に結合する
以下のコードは、指定したフォルダ内のすべての `.txt` ファイルを、一つのファイルに結合するスクリプトです。
‘ — 設定エリア —
strFolder = “C:\Data\Input\”
strOutputFile = “C:\Data\Output\Combined.txt”
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set objStreamOutput = CreateObject(“ADODB.Stream”)
‘ 出力ストリームの初期化
objStreamOutput.Type = 1 ‘ バイナリモード
objStreamOutput.Open
‘ フォルダ内のファイルを走査
For Each file In fso.GetFolder(strFolder).Files
If LCase(fso.GetExtensionName(file.Path)) = “txt” Then
Set objStreamInput = CreateObject(“ADODB.Stream”)
objStreamInput.Type = 1 ‘ バイナリモードで読み込み
objStreamInput.Open
objStreamInput.LoadFromFile file.Path
‘ 【重要】最初のファイル以外は、先頭3バイト(BOM)をスキップする
If objStreamOutput.Size > 0 Then
objStreamInput.Position = 3
End If
‘ 残りのデータをコピー
objStreamOutput.Write objStreamInput.Read
objStreamInput.Close
Set objStreamInput = Nothing
End If
Next
‘ ファイル保存
objStreamOutput.SaveToFile strOutputFile, 2 ‘ 2 = 上書き保存
objStreamOutput.Close
—
コードの深掘り:エンジニアの着眼点
このコードが「なぜ動くのか」、そして「なぜ壊れないのか」を解説します。
1. バイナリモード(Type = 1)の選択
`ADODB.Stream` を `Type = 2`(テキストモード)で開くと、VBScriptが勝手に文字コード変換を試みます。これが悲劇の始まりです。`Type = 1`(バイナリ)で扱うことで、データの内容を一切いじらず、そのまま「バイトの列」として結合できます。
2. Position = 3 の魔術
UTF-8のBOMは「EF BB BF」の3バイトです。2つ目以降のファイルに対し `Position = 3` を指定することで、先頭のBOMを無視して、純粋なデータ部分からコピーを開始します。これにより、結合後のファイル内にBOMが混入するのを防ぎます。
3. オブジェクトのライフサイクル管理
`ADODB.Stream` はメモリを消費します。ループのたびに `Set objStreamInput = Nothing` で解放し、`Close` を徹底することで、巨大なファイルを結合してもメモリリークを起こさない堅牢な構成にしています。
—
陥りやすいエラーと対策
- 「ファイルにアクセスできません」エラー:
これは、結合先のファイルが既に他のプログラムで開かれているか、出力先フォルダが存在しない場合に発生します。`fso.FolderExists` で事前チェックを行う習慣をつけましょう。
- 「Positionプロパティでエラー」:
ファイルが空(0バイト)の場合、`Position = 3` を設定するとエラーになります。読み込み前に `objStreamInput.Size` を確認するガード句を入れると完璧です。
—
最後に:ここをクリアすれば、あなたはもう脱・初心者です
VBScriptは古い言語だと言われがちですが、Windows環境における「OS直結のバイナリ操作」において、これほど身軽で強力なツールはありません。
今回扱った「ストリーム制御」の考え方は、VBScriptに限らず、C#やPowerShell、さらにはクラウドのデータ処理にも通じる「データの扱い方の本質」です。
まずはこのコードをコピペして、手元のCSVやログファイルで試してみてください。エラーが出たら、それは「OSと対話できた証」です。怖がらずに、少しずつ設定を変えて遊んでみてくださいね。
皆さんの自動化ライフが、より快適で正確なものになることを応援しています!
