【入門編】【超巨大ログ分割】数GBクラスのテキストをFSOで指定行数ごとに高速で小分けファイル出力する軽量バッチ – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!エンジニアリングの世界へようこそ。今日は、現場でよく直面する「数GBもある超巨大ログファイル」の絶望的な重さからあなたを救い出す、最高にクールで実用的なVBScriptのテクニックをお伝えします。

「Excelで開こうとしたらフリーズした…」
「メモ帳ですら『ファイルが大きすぎます』と怒られた…」

そんな絶望を味わったことはありませんか?
初学者のうちは、ファイルをすべてメモリに読み込もうとしてエラー(メモリ不足)でスクリプトがクラッシュしがちです。しかし、FSO(FileSystemObject)の`TextStream`を正しく手懐ければ、どれほど巨大なファイルであっても、メモリをほとんど消費せずにサクサクと小分けにすることができます。

ここをクリアすれば、VBScriptのファイル操作の基本はバッチリですよ。さあ、一緒にプロの技を身につけましょう!

—

なぜ「全部読み込み」はダメなのか?(FSOの本質)

VBScriptでファイルを読むとき、ついつい `ReadAll` メソッドで一気に全データを変数に放り込みたくくなりますよね。
しかし、数GBクラスのファイルをこれやってしまうと、OSの仮想メモリが悲鳴を上げ、最悪の場合はPC本体がフリーズします。

今回マスターするアプローチは 「ストリーム処理(1行ずつ読んで、書き出す)」 です。
川の流れ(Stream)をイメージしてください。水(データ)をバケツですべて汲み取るのではなく、目の前を流れる水をちょこちょこすくって別の場所へ流していくイメージです。これなら、どんなに大河のような大容量データでも、バケツ(メモリ)ひとつで処理できますよね。

—

【実践】超巨大ログを高速分割するVBScriptコード

以下のコードをメモ帳に貼り付け、拡張子を `.vbs` (例: `split_log.vbs`)として保存してください。

‘ ==============================================================================
‘ スクリプト名: SplitLargeLog.vbs
‘ 概要: 数GBクラスの巨大ログファイルを指定行数ごとに高速分割する
‘ ==============================================================================
Option Explicit

‘ — 設定エリア —
Dim targetFile, outputFolder, linesPerFile
targetFile = “C:\Logs\huge_server.log” ‘ 分割したい巨大ログファイルのパス
outputFolder = “C:\Logs\splitted\” ‘ 分割したファイルの出力先フォルダ
linesPerFile = 100000 ‘ 1ファイルあたりの最大行数(例: 10万行)

‘ — メイン処理の実行 —
Call SplitTextFile(targetFile, outputFolder, linesPerFile)

‘ ==============================================================================
‘ 関数名: SplitTextFile
‘ 引数: strFilePath (読込元ファイル), strOutDir (出力先), intMaxLines (分割行数)
‘ ==============================================================================
Sub SplitTextFile(strFilePath, strOutDir, intMaxLines)
Dim fso, tsIn, tsOut
Dim lineCount, fileIndex
Dim currentLine, outFileName

‘ 1. FileSystemObjectの生成
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 2. 入力ファイルの存在確認
If Not fso.FileExists(strFilePath) Then
WScript.Echo “エラー: 指定されたファイルが見つかりません。” & vbCrLf & strFilePath
Exit Sub
End If

‘ 3. 出力先フォルダの存在確認・自動生成
If Not fso.FolderExists(strOutDir) Then
fso.CreateFolder(strOutDir)
End If

‘ 4. 読み込み専用でテキストストリームを開く (ForReading = 1)
‘ ※ 第3引数の True/False は新規作成の有無。読み込みなのでFalse。最後の引数は文字コード(-1=Unicode, 0=ASCII/Shift_JIS等)
Set tsIn = fso.OpenTextFile(strFilePath, 1, False)

lineCount = 0
fileIndex = 1
Set tsOut = Nothing

‘ 5. ファイルの終端(AtEndOfStream)まで1行ずつループ処理
Do Until tsIn.AtEndOfStream
currentLine = tsIn.ReadLine

‘ 新規ファイルが必要なタイミング(初回、または前ファイルが上限に達した時)
If lineCount Mod intMaxLines = 0 Then
‘ すでに開いている出力ファイルがあれば閉じる(リソースの解放)
If Not (tsOut Is Nothing) Then
tsOut.Close
Set tsOut = Nothing
End If

‘ 連番ファイル名の生成 (例: log_001.txt, log_002.txt)
outFileName = strOutDir & “log_” & Right(“000” & fileIndex, 3) & “.txt”

‘ 書き込み用としてファイルを作成・オープン (ForWriting = 2, True = 新規作成許可)
Set tsOut = fso.CreateTextFile(outFileName, True)

fileIndex = fileIndex + 1
End If

‘ 出力ファイルに1行書き込み
tsOut.WriteLine currentLine
lineCount = lineCount + 1
Loop

‘ 6. 最後に開いていた出力ファイルを確実に閉じる
If Not (tsOut Is Nothing) Then
tsOut.Close
End If

‘ 7. 入力ストリームも閉じる
tsIn.Close

‘ 8. オブジェクトの完全解放(メモリリーク防止)
Set tsOut = Nothing
Set tsIn = Nothing
Set fso = Nothing

WScript.Echo “処理完了! ” & (fileIndex – 1) & ” 個のファイルに分割されました。”
End Sub

—

コードの重要なポイントを先輩が解説!

1. `OpenTextFile` と `CreateTextFile` の使い分け

FSOを使う上で最も大切なのは「リソースの適切な管理」です。

  • 読み込む側:`fso.OpenTextFile(path, 1)` (`1` は `ForReading`)
  • 書き込む側:`fso.CreateTextFile(path, True)` (新規作成・上書き許可)

これを適切に開閉することで、OSのファイルロックを防ぎ、メモリを極限まで節約できます。

2. 連番を美しく揃えるテクニック

ファイル名が `log_1.txt`, `log_2.txt` … となると、エクスプローラーで並び替えたときに `log_10.txt` が `log_2.txt` の前に来てしまいイライラしますよね。
そこで、このコードでは以下の技を使っています。

Right(“000” & fileIndex, 3)

これによって、`1` が `001` に、`12` が `012` に自動変換され、アルファベット順・数字順のソートが完璧になります。こういう細かな気配りが、プロのコードと素人のコードを分ける境界線です。

3. オブジェクトの明示的な破棄(解放)

スクリプトの最後で `Set tsOut = Nothing` のように、使ったオブジェクトを片っ端から `Nothing` に代入しています。VBScriptはスクリプト終了時に自動でガベージコレクションが走りますが、大きなファイルを扱うスクリプトでは、「使い終わったら即座にメモリから消す」 という習慣がバグを防ぐ最強の盾になります。

—

陥りがち・やりがちなエラーと対策

  • エラー:「書き込み権限がありません (Permission denied)」
  • 原因: 出力先フォルダ(`C:\Logs\splitted\` など)が存在しない、または読み取り専用になっている。
  • 対策: スクリプト内で `fso.FolderExists` を使って自動生成するロジックを入れておくか、書き込み権限のあるパスを指定してください。
  • エラー:「文字化けが発生する」
  • 原因: `OpenTextFile` の第3引数(FORMAT)の指定が、ログファイルの文字コード(UTF-8, Shift_JISなど)と一致していない。
  • 対策: 日本語のレガシーなログであればShift_JIS(デフォルト)、近年のUTF-8ログの場合は環境によってBOMの有無が影響します。必要に応じて `ADODB.Stream` オブジェクトへの切り替えを検討しますが、まずは上記コードで基本の動きを確認しましょう。

—

おわりに

いかがでしたか?
「VBScriptなんて古い技術…」と思うなかれ。Windows環境さえあれば追加のインストールなしで即座に動き、今回のような重いファイル処理の自動化において、今でも現場の縁の下の力持ちとして君臨しています。

ここをクリアしたあなたなら、もう「メモリ不足」に怯える必要はありません。
日々の面倒なファイル整理やログ解析の自動化に、ぜひこのコードを活用してみてくださいね。あなたのエンジニアライフが、より快適でスマートになりますように!

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