【テクニカル・上級編】【全角・半角混在処理】FSOでの文字列読み込み時にバイト数と文字数のギャップによるエラーを防ぐSafeRead術 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptを掌握する極限の知見:FSOとマルチバイト文字の深淵なる罠を制す

多くのエンジニアが「VBScriptは古い」と切り捨てる。だが、Windowsの心臓部で静かに動き続けるこのスクリプト言語こそ、OSの挙動を理解した者だけが使いこなせる「精密なメス」であることに気づいている者は少ない。

特に`Scripting.FileSystemObject (FSO)`を用いたファイル操作において、全角・半角が混在するテキストデータを扱う際、多くの初学者が「文字数」と「バイト数」の概念を混同し、システムを崩壊させている。今日は、その泥沼から脱却し、真に堅牢なコードを書くための秘儀を伝授しよう。

1. なぜFSOの `ReadAll` は「事故」を誘発するのか

VBScriptの内部処理はUnicode(UTF-16)で行われる。しかし、外部ファイルからデータを読み込む際、`OpenTextFile` が解釈する文字コードと、Windowsのロケール(Shift-JIS/CP932など)のギャップが、文字数計算に致命的なズレを生む。

典型的な失敗は、`Len()` 関数で文字数を計測し、`Mid()` や `Left()` で文字列を切り出す際に、マルチバイト文字の途中で切り出しが走ることだ。これにより発生する「化け」は、ログ出力やDB格納時にシステムを停止させる爆弾となる。

2. 【秘伝】ADODB.Streamによる「SafeRead」の極意

FSOの `OpenTextFile` は、文字エンコーディングの厳密な制御が困難だ。本気で安定性を求めるなら、`ADODB.Stream` オブジェクトを召喚せよ。これにより、文字コードを明示的にバイナリ単位で制御し、メモリ上での安全な変換を保証する。

‘ SafeRead: マルチバイトを考慮した安全なファイル読み込み
Function SafeReadTextFile(filePath, charset)
Dim adoStream
Set adoStream = CreateObject(“ADODB.Stream”)

‘ バイナリモードで開き、エンコーディングを強制指定
adoStream.Type = 2 ‘ adTypeText
adoStream.Charset = charset ‘ “Shift_JIS” や “UTF-8” を指定
adoStream.Open

adoStream.LoadFromFile filePath

‘ メモリに全展開せず、必要な部分のみを読み込む設計がベスト
SafeReadTextFile = adoStream.ReadText(-1) ‘ adReadAll

‘ ライフサイクルの管理:オブジェクトは即座に解放する
adoStream.Close
Set adoStream = Nothing
End Function

3. 文字数とバイト数のギャップを埋める「API的思考」

VBScriptの標準 `Len()` は文字数(Unicodeの文字数)を返す。しかし、システム連携先が「バイト数」を要求する場合、これだけでは足りない。ここで、Windows APIの知見を活用する。

もし、どうしてもバイト単位での制御が必要ならば、`ADODB.Stream` をバイナリモードで開き、`Read` メソッドでバイナリデータとして切り出してから文字列変換を行うのが、伝説のアーキテクトが辿り着く最終到達点だ。

実践:バイト指定切り出しのロジック

‘ バイト数による厳密な文字列切り出し(マルチバイト安全)
Function SafeMidByte(strInput, startByte, lengthByte)
Dim adoStream
Set adoStream = CreateObject(“ADODB.Stream”)

adoStream.Type = 1 ‘ adTypeBinary
adoStream.Open

‘ 文字列をバイナリとして書き込み
Dim binData
binData = StringToBinary(strInput) ‘ 文字列をバイナリ変換する関数を併用
adoStream.Write binData

‘ 特定のバイト位置へシークして読み込み
adoStream.Position = startByte – 1
SafeMidByte = BinaryToString(adoStream.Read(lengthByte))

adoStream.Close
Set adoStream = Nothing
End Function

4. 伝説のエンジニアが守る「鉄の掟」

1. オブジェクトの明示的解放: `Set obj = Nothing` を怠るな。VBScriptのガベージコレクションを信じてはいけない。特に長時間稼働するタスクでは、メモリリークは「死」と同義だ。
2. エラーハンドリング: `On Error Resume Next` を使うのは良い。だが、その直後に必ず `If Err.Number <> 0 Then` でエラーを拾い、適切にログを吐き出せ。エラーを握りつぶすのはエンジニアの恥だ。
3. 文字コードの固定: 「システムデフォルト」に頼るな。読み込み元と書き込み先のエンコーディングは、必ずコード内で明示せよ。これがレガシー環境を生き抜く唯一の道だ。

最後に:VBScriptという選択

「なぜ今さらVBScriptなのか」と問われたら、こう答えてほしい。
「OSの深層に最も近い場所で、余計なオーバーヘッドなしにロジックを叩き込めるからだ」と。

技術は流行を追うものではない。環境の本質を捉え、その制約の中で最大限のパフォーマンスを引き出すことこそが、真のエンジニアリングである。この知見が、君の構築するシステムの堅牢な礎となることを願っている。

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