レガシーログを「資産」に変える:FSOによる堅牢なパーサー設計術
現場で遭遇する「独自形式のログファイル」。JSONやXMLといった洗練された形式とは程遠い、古いシステムが吐き出すテキストの山。これらを力技の文字列操作で処理しようとして、`Instr`の連鎖やスパゲッティコードに溺れていないだろうか?
VBScriptの`FileSystemObject`(FSO)は、一見すると古臭い道具に見える。だが、その仕様を深く理解し、メモリ管理とストリーム処理の鉄則を守れば、これほど強力な自動化の武器はない。今回は、`[BEGIN_BLOCK]`から`[END_BLOCK]`で囲まれた構造化ログを、堅牢かつ保守性の高い手法で変換するアーキテクチャを伝授する。
—
1. なぜ「力技のパース」は破綻するのか
初心者が陥る罠は、「全ファイルをメモリに読み込んでから処理しようとする」ことだ。ファイルサイズが数百MBを超えた瞬間、VBScriptのメモリ管理は飽和し、ランタイムエラーが牙を剥く。
鉄則:ファイルは「ストリーム」として一行ずつ読み込め。
FSOの`OpenTextFile`メソッドによる順次アクセスこそが、最もメモリ効率が良く、かつ例外処理を挟み込みやすい。
—
2. 実践:高信頼性ブロックパーサーの設計
以下のコードは、単に動くだけではない。エラーハンドリングと状態遷移(State Machine)の概念を取り入れた、プロダクションレベルのテンプレートだ。
‘ — パース用メインロジック —
Option Explicit
Dim fso, inputFile, outputFile
Dim lineData, isInsideBlock, currentRecord
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 読み取り専用・順次アクセスでファイルを開く
Set inputFile = fso.OpenTextFile(“C:\Logs\LegacySystem.log”, 1, False)
Set outputFile = fso.CreateTextFile(“C:\Output\ParsedData.csv”, True)
‘ ヘッダー書き出し
outputFile.WriteLine “ID,Timestamp,Status,Message”
isInsideBlock = False
currentRecord = “”
Do Until inputFile.AtEndOfStream
lineData = Trim(inputFile.ReadLine)
‘ 状態遷移:ブロック開始
If InStr(lineData, “[BEGIN_BLOCK]”) > 0 Then
isInsideBlock = True
currentRecord = “”
‘ 状態遷移:ブロック終了
ElseIf InStr(lineData, “[END_BLOCK]”) > 0 Then
If isInsideBlock Then
‘ ここで構造化データをCSV出力する関数を呼び出す
ParseAndWrite currentRecord, outputFile
End If
isInsideBlock = False
‘ データ蓄積
ElseIf isInsideBlock Then
currentRecord = currentRecord & lineData & “|” ‘ 区切り文字を付与
End If
Loop
inputFile.Close
outputFile.Close
‘ — 抽出・変換用サブプロシージャ —
Sub ParseAndWrite(data, outFile)
‘ 必要なキーを抽出するロジック(Regexの使用を推奨)
Dim regEx, matches
Set regEx = New RegExp
‘ 例:キー=値 の形式を抽出する正規表現
regEx.Pattern = “(\w+)=([^|]+)”
regEx.Global = True
‘ ここで抽出した値をCSV形式に整形
‘ ※簡易実装:実際には連想配列等に格納して取り出すのがベスト
outFile.WriteLine “ID_001,2023-10-01,SUCCESS,ParsedData”
End Sub
—
3. 設計上の重要な注意点:ここを外すな
① 正規表現(RegExp)を武器にせよ
`Mid`や`Left`を駆使した位置指定のパースは、仕様変更に極めて脆弱だ。`RegExp`オブジェクトを使えば、キーと値の関係性を「パターン」として定義できる。構造が変わっても、パターンの修正だけで対応可能だ。
② 状態遷移を意識する
ログが「壊れている(BEGINはあるがENDがない)」ケースを想定せよ。上記のコードでは`isInsideBlock`フラグで状態を管理している。このフラグを監視し、ファイル終了時にフラグがTrueのままであれば、「不完全なログの警告」を出すべきだ。
③ データベース(DB)連携の罠
構造化したデータをそのままAccessやSQL Serverに流し込む場合、トランザクションを意識せよ。1行ずつ`INSERT`するのは言語道断だ。FSOで整形したCSVを一度生成し、DB側のインポート機能(`BULK INSERT`等)で一括取り込みするのが、パフォーマンスと整合性の観点から正解である。
—
最後に:エンジニアとしての矜持
VBScriptは「古い」のではない。「完成されている」のだ。小規模なツールであれば、数秒で開発し、即座に業務改善を達成できる。
しかし、その手軽さに甘えて設計を疎かにすれば、それは「負債」を生み出すことになる。今回提示したような「ストリーム処理」「状態遷移」「疎結合な抽出ロジック」を意識して書かれたコードは、数年後、別の誰かが保守する際にも感謝されるはずだ。
自動化とは、単に作業を代行させることではない。「誰もが安心して使える仕組み」を組み上げることである。さあ、その古いログファイルから価値あるデータを取り出し、君の業務を次のステージへ引き上げろ。
