【入門編】【大容量ファイルパース】StdIn / StdOut ストリームパイプライン処理による低メモリ消費ログ解析 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは! VBScriptの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩抜け出し、「本物のシステム自動化」を自分の手でコントロールしたいあなたへ。

今回は、現場でよく直面する「数GBもある巨大なログファイルから、特定のキーワードだけを秒速で抜き出したい」という難題に挑戦します。

「VBScriptで大きなファイルを扱うと、メモリーエラー(メモリ不足)ですぐフリーズする……」
そんな諦めを抱いていませんか? 大丈夫です。今回のテクニックをマスターすれば、PCのメモリをほとんど消費せず、どれほど巨大なファイルでも軽々とさばけるようになりますよ。

ここをクリアすれば、あなたのVBScriptのスキルは一気にプロの領域へ到達します。さあ、一緒に扉を開きましょう!

1. なぜ巨大ファイルでVBScriptはフリーズするのか?

初学者がやりがちなのが、次のようなコードです。

‘ 【やってはいけないアンチパターン】
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ ファイル全体を1つの変数に丸ごと読み込む(メモリ爆食いの原因!)
content = fso.OpenTextFile(“huge_log.txt”, 1).ReadAll
lines = Split(content, vbCrLf)

数GBのファイルを `ReadAll` でメモリに読み込もうとすると、Windowsは悲鳴を上げます。なぜなら、ファイルサイズ以上のメモリ(場合によってはその数倍の作業領域)をRAM上に確保しようとするからです。結果は「メモリ不足(Out of memory)」で強制終了です。

解決の鍵:ストリーム・パイプライン処理

発想を逆転させましょう。「ファイルをメモリに全部読み込むな。1行ずつ読んで、用が済んだら流せ(ストリーミング)」のです。

さらに、Windowsの標準機能であるWSH(Windows Script Host)の標準入出力(StdIn / StdOut)をパイプ(`|`)で繋ぐことで、外部の強力なコマンドとも連携できる極限のメモリ節約システムが完成します。

2. メモリ消費量「ほぼゼロ」を実現するアーキテクチャ

今回の仕組みを図解すると、以下のようになります。

[巨大ログファイル]
│ (1行ずつ読み込み)

[VBScript] ──(StdIn)──> 【判定フィルター】 ──(StdOut)──> [抽出結果]

VBScriptは常に「たった1行分の文字列」しかメモリに保持しません。そのため、ファイルが何ギガバイトであっても、消費メモリは常に数キロバイトのまま一定という驚異的なパフォーマンスを発揮します。

3. 実装コード:ストリーミング・ログパーサー

それでは、実際の現場でそのまま使える実用コードを公開します。
デスクトップなどに `log_parser.vbs` という名前で保存してください。

‘ ==============================================================================
‘ スクリプト名: log_parser.vbs
‘ 概要: 標準入力から1行ずつログを受け取り、特定キーワードを含む行だけを
‘ 標準出力に吐き出すストリーミング・フィルター
‘ 使い方: cscript //nologo log_parser.vbs < huge_log.txt > result.txt
‘ ==============================================================================

Option Explicit

Dim objStdIn, objStdOut
Dim strLine, targetKeyword, matchCount

‘ 標準入力(StdIn)と標準出力(StdOut)のオブジェクトを取得
Set objStdIn = WScript.StdIn
Set objStdOut = WScript.StdOut

‘ 検索したいキーワード(例: エラーログを抽出)
targetKeyword = “ERROR”
matchCount = 0

‘ 標準ストリームの終端(AtEndOfStream)に達するまでループ
‘ ※ファイルを一括読み込みせず、1行ずつ流し込むためメモリを食いません
Do While Not objStdIn.AtEndOfStream
‘ 1行だけ読み込む
strLine = objStdIn.ReadLine

‘ 指定したキーワードが含まれているかチェック
If InStr(strLine, targetKeyword) > 0 Then
‘ 条件に一致した行だけを標準出力へ書き出す
objStdOut.WriteLine strLine
matchCount = matchCount + 1
End If
Loop

‘ 処理結果をエラー出力(StdErr)へ通知(標準出力を汚さないためのプロの技)
WScript.StdErr.WriteLine “処理完了。一致した行数: ” & matchCount

‘ オブジェクトのクリーンアップ(メモリリークを防ぐ作法)
Set objStdOut = Nothing
Set objStdIn = Nothing

4. このコードの極意とポイント解説

① `WScript.StdIn` と `AtEndOfStream`

ファイル全体を一気に読み込むのではなく、水道の蛇口をひねるように「今、流れてきている1行」だけを `ReadLine` で取得します。`AtEndOfStream` は、ファイルの最後まで到達したかを判定する安全装置です。

② なぜ `cscript` で実行するのか?

VBScriptには、GUIベースの `wscript.exe` と、CUI(コマンドプロンプト)ベースの `cscript.exe` があります。
標準入出力(StdIn / StdOut)をパイプで繋ぐ今回の処理では、必ずコマンドプロンプト上で `cscript` を使って実行する必要があります。

5. 現場で使える実践的な実行コマンド

作成したVBScriptは、コマンドプロンプトから次のように呼び出します。ここが最大の醍醐味です!

cscript //nologo log_parser.vbs < huge_application.log > filtered_errors.txt

  • `< huge_application.log` : 数GBあるログファイルを、標準入力を通してVBScriptに1行ずつ流し込みます。
  • `> filtered_errors.txt` : VBScriptが標準出力(`StdOut`)に書き出した「ERROR行」だけを、新しいファイルに綺麗に保存します。

このパイプライン構造により、VBScript単体では扱えないような巨大データも、WindowsのOS機能と美しく協調して高速処理できるのです。

6. 初学者が陥りやすい罠とエラー回避の知見

1. 「入力エラー (Input/output error)」が出る

  • 原因: ダブルクリックでVBScriptを直接起動してしまった場合、標準入力(`StdIn`)が存在しないためエラーになります。
  • 対策: 必ずコマンドプロンプトから `cscript` コマンド経由で実行してください。

2. 文字化けが発生する

  • 原因: 読み込むログファイルの文字コード(UTF-8やShift-JISなど)と、コマンドプロンプトのコードページが一致していない場合におきます。
  • 対策: 必要に応じて事前に `chcp 65001`(UTF-8に変更)などを実行して環境を整えておきましょう。

さいごに

お疲れ様でした!
今回は、VBScriptの裏側にある「ストリーム処理」という強力な概念に触れました。

マクロの記録の延長線上にあるコードは、データが大きくなるとすぐに限界を迎えます。しかし、今回学んだ `StdIn` / `StdOut` を使ったパイプライン処理の知見があれば、あなたはもう「メモリ不足に怯える初心者」ではありません。どんなに巨大なログが来ようとも、涼しい顔で自動化を成し遂げられる優秀なエンジニアです。

ここをクリアしたあなたなら、どんな業務自動化の壁も乗り越えられます。ぜひ、実際の現場のログ解析で試してみてくださいね!

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