【テクニカル・上級編】【BOMなしUTF-8テキスト結合】ADODB.Stream を利用したヘッダー保持とBOM破壊を抑止する大容量ファイル結合 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptを極める:BOMなしUTF-8の「外科手術的」結合術

Windowsの自動化において、VBScriptはもはや「レガシー」というレッテルを貼られがちだ。しかし、真のアーキテクトは知っている。OSの深層に根ざしたWSH(Windows Script Host)の実行環境こそ、軽量かつ高速なインフラ連携の要であることを。

特に、データ連携の現場で頻出する「BOMなしUTF-8」のハンドリング。標準の `FileSystemObject` (FSO) はUTF-16 LEに固執し、BOMを付与する。これを力技で結合すれば、中間ファイルにBOMが混入し、後続のシステム(Linux環境やクラウドAPI)がエラーを吐く。

今日は、`ADODB.Stream` をバイナリレイヤーで操作し、メモリを浪費せずに大規模ファイルを結合する「外科手術」のようなコードを伝授する。

なぜADODB.Streamなのか

`FileSystemObject` を使うのは、テキスト処理の基本だが、ストリーム制御においては無力だ。`ADODB.Stream` は、本来データベースのBLOBを扱うためのものだが、その真価は「バイナリの断片を結合する際の透過性」にある。

UTF-8のBOM(`EF BB BF`)を回避するには、テキストモードを捨て、バイナリとして読み込み、連結するしかない。このアプローチは以下のメリットをもたらす。

1. メモリ効率: 大容量ファイルでもバッファを制御することで、OSへの負荷を最小限に抑える。
2. 整合性: BOMを物理的に除外して読み込むため、後続処理で「予期せぬ文字化け」が起きない。
3. 移植性: Windows標準のコンポーネントのみを使用するため、ライブラリのインストールは一切不要。

極限の結合スクリプト:実装と解析

以下は、指定フォルダ内のBOMなしUTF-8ファイルを結合し、単一の出力ファイルへ書き出すための堅牢なスクリプトである。

‘ — 極限のファイル結合スクリプト (ConcatUTF8.vbs) —
Option Explicit

Dim fso, folder, files, file
Dim outStream, inStream
Dim targetFolder, outputFile

targetFolder = “C:\Data\Logs”
outputFile = “C:\Data\Output\Combined.log”

Set fso = CreateObject(“Scripting.FileSystemObject”)
Set outStream = CreateObject(“ADODB.Stream”)

‘ 出力ストリームをバイナリモードで初期化
outStream.Type = 1 ‘ adTypeBinary
outStream.Open

Set folder = fso.GetFolder(targetFolder)

For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “txt” Then
Set inStream = CreateObject(“ADODB.Stream”)
inStream.Type = 1 ‘ adTypeBinary
inStream.Open
inStream.LoadFromFile file.Path

‘ BOM (3バイト) をスキップするためのシーク処理
If inStream.Size >= 3 Then
inStream.Position = 3
End If

‘ 残りのデータを読み込み、出力ストリームへ追記
outStream.Write inStream.Read

inStream.Close
Set inStream = Nothing
End If
Next

‘ 書き込みとクリーンアップ
outStream.SaveToFile outputFile, 2 ‘ adSaveCreateOverWrite
outStream.Close
Set outStream = Nothing
Set fso = Nothing

アーキテクトの視点:コードの深層

このコードには、ただ動くだけではない「意図」が組み込まれている。

1. `inStream.Position = 3` の必然性

UTF-8のBOMは先頭の3バイト `0xEF, 0xBB, 0xBF` で構成される。`Position = 3` とすることで、ストリームのポインタをBOMの直後に強制移動させている。もしファイルにBOMが含まれていない場合は、この処理を条件分岐で制御する必要があるが、現代のシステム連携では「BOMあり/なしが混在する」ケースが多いため、正規化処理を前段に置くのがアーキテクチャの鉄則である。

2. オブジェクトのライフサイクル管理

`Set inStream = Nothing` をループ内で明示的に行っているのは、COMオブジェクトの解放をメモリ管理者に任せないためだ。VBScriptのガベージコレクションは非力であり、数千ファイルの結合を行う際、解放を怠ればメモリリークによるプロセス終了を招く。

3. パフォーマンスの最適化

`outStream.Write inStream.Read` は、メモリ内に全データを展開する。もし結合対象がギガバイト単位に及ぶ場合は、`inStream.Read(chunkSize)` を利用してバッファリングを行う実装に切り替える必要がある。これはエンジニアの腕の見せ所だ。

結論:レガシーを「武器」にする

VBScriptは過去の遺物ではない。Windows環境において、特定の権限や設定なしに実行可能な軽量なバイナリ制御ツールとして、今なお最強の選択肢の一つだ。

APIやモダンな言語(Python/Go)に頼るまでもない、数メガバイトのログ処理や、自動化の初動において、この「ADODB.Streamによる直打ち」を使いこなせるかどうか。それが、凡百のスクリプターと、伝説的な自動化エンジニアを分かつ境界線となる。

さあ、目の前の退屈な手作業を、このアーキテクチャで根絶やしにしてほしい。それがエンジニアの矜持というものだ。

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