【VBScript極意】混在する改行コードを制する。FSOによる「完全なる標準化」の実装術
現場の自動化において、最も地味で、かつ最も多くのシステム障害を引き起こす元凶。それは「改行コードの不一致」だ。
Linuxから吐き出された `LF`、古のMacを引きずる `CR`、そしてWindowsの `CRLF`。これらが混在したテキストファイルを、何も考えずに `ReadLine` して `WriteLine` するだけのコードで処理しようとしていないか? もしそうなら、あなたのツールは「時限爆弾」を抱えているに等しい。
今日は、FSO(FileSystemObject)を駆使し、あらゆる異物混入を許さない「堅牢な改行コード標準化エンジン」の設計思想と実装を授ける。
—
1. なぜ「ReadLine」一発ではダメなのか
多くのエンジニアが犯す最大の過ちは、`TextStream.ReadLine` をループさせるだけのコードだ。
`ReadLine` は「CR, LF, CRLF」を自動的に認識して削除するが、出力時に自動でCRLFを付与するという仕様がある。これが災いし、読み込み時に元の改行コードが何だったのかという情報が完全に失われる。
さらに恐ろしいのは、「読み込み時に改行として認識されない特殊なバイト列」や、「ファイルの末尾が改行で終わっていない場合」の挙動だ。これらを放置すれば、後続のデータベース投入処理やCSVインポートで致命的なエラーを引き起こす。
—
2. 堅牢な設計へのアプローチ:ストリームの直視
我々が目指すべきは、「読み込み」と「書き込み」を完全に分離し、改行コードを一度「標準化」した上で再構成するアプローチだ。
プロダクションコード:NormalizeLineEndings.vbs
このスクリプトは、入力ファイルの文字コードを判定し、改行コードをWindows標準(CRLF)に統一して書き出す。
Option Explicit
‘ —————————————————————————
‘ 関数: NormalizeLineEndings
‘ 目的: 任意の改行コードが混在するファイルを読み込み、CRLFのみに変換して保存
‘ —————————————————————————
Sub NormalizeLineEndings(strInputPath, strOutputPath)
Dim objFSO, objFile, strContent
Set objFSO = CreateObject(“Scripting.FileSystemObject”)
‘ 1. バイナリモードではなくテキストモードで開く(まずはメモリへ)
‘ 大規模ファイルの場合はここをストリーム分割読み込みにする必要があるが、
‘ 一般的な業務データなら一旦メモリに乗せるのが最もバグが少ない
Set objFile = objFSO.OpenTextFile(strInputPath, 1, False)
strContent = objFile.ReadAll
objFile.Close
‘ 2. 正規表現による置換で改行コードを正規化
‘ LF(Chr(10))およびCR(Chr(13))を一度すべてCRLFに置換し、
‘ 重複したCRを削除することで、混在環境を完全に無効化する
Dim objRegEx
Set objRegEx = New RegExp
objRegEx.Global = True
‘ まず、すべてのLFをCRLFに変換
objRegEx.Pattern = “\r\n|\n|\r”
strContent = objRegEx.Replace(strContent, vbCrLf)
‘ 3. 出力処理
‘ WriteLineを使用せず、Writeで書き出すことで、意図しない改行追加を防ぐ
Dim objOutFile
Set objOutFile = objFSO.CreateTextFile(strOutputPath, True)
objOutFile.Write strContent
objOutFile.Close
Set objRegEx = Nothing
Set objFSO = Nothing
WScript.Echo “処理完了: ” & strOutputPath
End Sub
‘ 使用例
NormalizeLineEndings “C:\data\input.txt”, “C:\data\output_normalized.txt”
—
3. 実務で「生き残る」ための3つの鉄則
このコードをそのまま現場に投入する際、以下の3点だけは意識しておいてほしい。
① 大容量ファイルへの対応(メモリ管理)
上記のコードは `ReadAll` を使用している。これはファイルサイズが数MB程度であれば高速だが、数GBに及ぶログファイルを扱う場合はメモリを圧迫する。その場合は `ReadLine` でバッファリングしつつストリームを生成する設計に切り替える必要があるが、まずは「メモリに載るサイズ」であることを前提に、処理速度と堅牢性のバランスを取るのが正解だ。
② 文字コードの闇(BOM問題)
`OpenTextFile` は、文字コードを明示的に指定しない場合、OSのデフォルト(主にShift-JIS)として開く。もしUTF-8(BOMなし)のファイルを扱う場合は、`ADODB.Stream` オブジェクトを使用して、エンコーディングを明示的に `utf-8` に設定して読み込む必要がある。FSOは便利な反面、Unicodeの扱いは非常に繊細だ。
③ エラーハンドリングは「呼び出し元」で行え
このスクリプトは汎用パーツとして設計している。ファイルがロックされている、パスが存在しない、といったIOエラーは、関数内で `On Error Resume Next` で誤魔化さず、呼び出し元のメイン処理で捕捉せよ。それが「保守性の高いコード」の絶対条件だ。
—
最後に:エンジニアとしての矜持
「動けばいい」というコードは、数ヶ月後の自分を苦しめる呪いになる。
今回紹介した「正規表現を用いた改行の置換」は、一見遠回りに見えるかもしれない。しかし、複雑な改行の組み合わせをロジックで追いかけるよりも、「一度すべてをCRLFに置換する」という圧倒的な力技の方が、結果としてバグの入り込む余地を限りなくゼロにする。
VBScriptは古い言語かもしれない。だが、その仕様を深く理解し、泥臭いファイル処理を洗練されたアルゴリズムで解決する。それこそが、伝説的な自動化エンジニアの歩む道だ。
さあ、このスクリプトをあなたの武器に加え、現場の無秩序なファイルを一掃してやってくれ。
