【入門編】【初心者向け】TextStreamのAtEndOfLineプロパティを用いた行末記号判定と安全な改行文字パース入門 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク
スポンサーリンク

【VBScript極意】TextStreamのAtEndOfLineを使いこなし、ファイルの「境界線」を支配する

こんにちは。現場で数々の自動化プロジェクトを設計してきた、チーフアーキテクトの私です。

あなたが今、「Excelのマクロ記録ではできないことを、VBScriptで実現したい」と考えているのなら、素晴らしい一歩を踏み出しましたね。マクロ記録は「操作の録画」であって、「ロジックの構築」ではありません。ここから先は、あなたの手で「コンピュータに思考させる」フェーズに入ります。

今日扱うテーマは、ファイル操作における「精密な制御」です。
多くの初心者は、ファイルを読み込む際に `ReadAll`(全読み込み)や `Split`(分割)といった、力技のメソッドに頼りがちです。しかし、プロのエンジニアは違います。私たちは「ストリーム(情報の流れ)」を意識し、メモリを浪費せず、かつデータの境界線をミリ単位で正確に捉える手法を選びます。

その鍵となるのが、`TextStream` オブジェクトの `AtEndOfLine` プロパティです。

1. 「ストリーム」という考え方を知っていますか?

コードに入る前に、大切な概念を一つ共有しておきましょう。
ファイルを扱うとき、コンピュータの内部ではファイル全体がメモリにドカンと載るのではなく、「読み取り位置(ポインタ)」が、川の流れ(ストリーム)のようにデータの上を移動しています。

  • `AtEndOfStream`: 「川の終点(ファイルの末尾)」に到達したか?
  • `AtEndOfLine`: 「今の行の終点(改行の直前)」に到達したか?

この違いを理解しているかどうかが、初心者とプロフェッショナルを分ける境界線になります。

2. AtEndOfLine プロパティの正体

`AtEndOfLine` は、読み取り位置(ポインタ)が「現在の行の末尾(改行コードの直前)」にある場合に `True` を返すプロパティです。

「え? `ReadLine` で一行ずつ読めば、勝手に改行で区切られるじゃないか」と思いましたか?
鋭いですね。確かに、単純な処理ならそれで十分です。

しかし、次のようなケースを想像してみてください。
> 「一行の中に複数のデータが入っている。特定の文字(例えばカンマやスペース)を探しながら読み進めたいが、行の終わりを超えて次の行のデータまで読み取ってしまうのは避けたい」

ここで `AtEndOfLine` が真価を発揮します。行の境界線を「見張り」ながら、一文字ずつ、あるいは特定の長さずつ慎重にデータを読み進めることができるのです。

3. 実践:安全な文字パース・テクニック

それでは、実際にコードを見てみましょう。
今回は、「一行ずつ読み込み、その中で一文字ずつチェックしながら、行の終わりを検知する」という、非常に精密なパース(解析)の例を作成しました。

' =================================================================
' 【実践】TextStreamを用いた精密な行末検知パース
' 目的:各行を1文字ずつ読み込み、行末に到達した瞬間に特殊な処理を行う
' =================================================================

Option Explicit

Dim fso, ts, filePath, strChar, lineCount

' 解析対象のファイルパス(環境に合わせて変更してください)
filePath = "C:\temp\sample_data.txt"

Set fso = CreateObject("Scripting.FileSystemObject")

' ファイルの存在確認(プロの基本:エラーを未然に防ぐ)
If Not fso.FileExists(filePath) Then
    WScript.Echo "Error: ファイルが見つかりません。"
    WScript.Quit
End If

' ファイルを読み取り専用(1)で開く
Set ts = fso.OpenTextFile(filePath, 1)

lineCount = 0

' 1. まずはファイルの末尾(AtEndOfStream)に達するまでループ
Do While Not ts.AtEndOfStream
    lineCount = lineCount + 1
    WScript.Echo "--- Line " & lineCount & " を解析中 ---"

    ' 2. 行の末尾(AtEndOfLine)に達するまで、1文字ずつ読み進める
    ' ※ここが AtEndOfLine を活用する核心部です
    Do While Not ts.AtEndOfLine
        ' 1文字だけ読み込む
        strChar = ts.Read(1)
        
        ' ここで読み取った文字に対して、何らかのロジック(判定など)を行う
        ' 今回はデモンストレーションとして、文字を表示するだけ
        WScript.Echo "文字: [" & strChar & "]"

        ' 【応用】もし特定の文字を見つけたら、その場で処理を中断する等の制御が可能
        If strChar = "!" Then
            WScript.Echo "  -> 特殊文字 '!' を検知しました。"
        End If
    Loop

    ' 3. 行末に到達した後の処理
    ' ReadLine を使うと、改行コードを飛ばして次の行の先頭へ移動します
    ts.ReadLine 
    WScript.Echo "  -> 行の終端に到達しました。"
Loop

' リソースの解放(メモリリークを防ぐための鉄則)
ts.Close
Set ts = Nothing
Set fso = Nothing

WScript.Echo "解析が正常に完了しました。"

コードの解説

1. 二重のループ構造:

  • 外側の `Do While Not ts.AtEndOfStream` は、「ファイル全体」を走査するためのものです。
  • 内側の `Do While Not ts.AtEndOfLine` は、「現在の行の中」を走査するためのものです。

2. `ts.Read(1)`:

  • `ReadLine`(一行丸ごと)ではなく、`Read(n)`(n文字分)を使うことで、ポインタを極めて細かくコントロールしています。

3. `ts.ReadLine`(ループの最後):

  • 内側のループを抜けたとき、ポインタは「行末(改行の直前)」にあります。そのまま次の文字を読もうとすると改行コードを拾ってしまうため、`ReadLine` を一度呼ぶことで、ポインタを「次の行の先頭」へスマートにジャンプさせています。

4. 陥りやすい「罠」と回避策

このテクニックを使う上で、初心者が必ずと言っていいほどハマるポイントが2つあります。

① 空行の扱い

ファイルに空行(改行だけの行)がある場合、`AtEndOfLine` は即座に `True` を返します。内側のループが一度も実行されないため、ロジックによっては「何も処理されなかった」と勘違いしてしまうことがあります。空行を許容するのか、スキップするのかを設計段階で決めておきましょう。

② 改行コードの不一致

VBScriptの `TextStream` は、基本的には `CRLF` (Windows標準) を想定していますが、ファイルが `LF` (Unix系) のみで構成されている場合、`AtEndOfLine` の挙動が意図せず変わることがあります。
ファイルを `OpenTextFile` で開く際、第4引数(Format)に `TristateTrue` (Unicode) などを指定する場合、文字コードの違いが境界線の判定に影響を与えることを忘れないでください。

5. まとめ:ここをクリアすれば、基本はバッチリですよ

今回のポイントを復習しましょう。

  • `AtEndOfStream` はファイルの終わり、`AtEndOfLine` は行の終わりを見張る。
  • `Read(n)` を組み合わせることで、一行の中を精密にスキャンできる。
  • メモリ効率:巨大なファイルを `ReadAll` で読み込むのは、メモリを食いつぶす危険な行為。ストリーム操作こそが正解。

「とりあえず動く」コードから、「どんなデータが来ても、効率的かつ正確に動く」コードへ。
この `AtEndOfLine` の感覚を掴めたあなたは、もう単なる「マクロ記録の利用者」ではありません。立派な「オートメーション・エンジニア」への道を歩み始めています。

次は、さらに複雑なデータ構造(CSVのパースや、特定のパターン抽出)に挑戦してみましょう。応援していますよ!

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