【入門編】【実務中級者向け】Shift_JIS非対応の環境依存文字(機種依存文字)をFSO読み込み時に検知・無害化置換するバッチ – VBScript (Visual Basic Scripting Edition)解析バイブル

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

文字化けの連鎖を断ち切れ。FSOとADODB.Streamを使いこなす「データクレンジング」の極意

「昨日まで動いていたバッチが、今日突然エラーを吐いて止まった……。原因を調べたら、ファイルの中に『①』や『㍉』といった機種依存文字が紛れ込んでいた」

業務自動化の現場で、エンジニアが一度は頭を抱えるのがこの「文字コードの壁」です。

こんにちは。今日は、VBScriptを使ってファイル操作を行う際、多くの人が陥る「文字化け」と「システム連携不具合」という深い沼を、どうやってスマートに回避するかについてお話ししましょう。

単に「ファイルを読み込む」だけなら簡単です。しかし、実務で求められるのは「汚れたデータを、システムが受け入れられる綺麗な形に整えてから渡す」という、一歩踏み込んだ「クレンジング(浄化)」の技術です。

ここをマスターすれば、あなたの作るスクリプトは、単なる「作業の自動化」から「プロフェッショナルなデータパイプライン」へと進化します。さあ、一緒に見ていきましょう。

1. なぜ「丸数字」がシステムを破壊するのか?

まずは敵を知ることから始めましょう。

Windowsの標準的なテキスト形式(Shift_JIS / ANSI)は、非常に歴史が長く、安定しています。しかし、Unicode(UTF-8など)が普及した現代では、Shift_JISの規格外にある文字——いわゆる「機種依存文字(環境依存文字)」が、システム間の橋渡しを阻む最大の要因になります。

陥りやすいエラーのメカニズム

1. FSOの限界: `FileSystemObject` (FSO) の `OpenTextFile` メソッドは、基本的にシステムのデフォルト文字コード(日本語環境ならShift_JIS)でファイルを読み込もうとします。
2. 情報の欠落: FSOが「理解できない文字(Unicode文字など)」に遭遇すると、エラーを出すのではなく、黙って「?」に置き換えてしまうことがあります。
3. 不可逆的な破壊: 一度「?」に変換されて保存されたファイルは、もう元の文字には戻せません。これが、データクレンジングが重要である最大の理由です。

2. アーキテクチャの設計図:FSOとADODB.Streamの使い分け

ここで、伝説的なエンジニアが必ず意識する「オブジェクトの役割分担」の話をしましょう。

初心者は何でもかんでも `FileSystemObject` で解決しようとしますが、それは間違いです。

  • FileSystemObject (FSO): 「ファイルやフォルダの存在確認」「移動」「削除」「ディレクトリ構造の把握」といった、「ファイルシステムそのものの操作」に特化させます。
  • ADODB.Stream: 「文字コードを指定して読み込む」「バイナリとして扱う」「Unicodeを正しく解釈する」といった、「ファイルの中身(コンテンツ)の操作」に特化させます。

今回のミッションでは、「FSOでファイルを探し、ADODB.Streamで中身を安全に読み込み、クレンジングして書き出す」というハイブリッドな戦略をとります。

3. 実践:データクレンジング・スクリプト

では、実際に「機種依存文字を検知し、安全な文字に置換する」スクリプトを書いてみましょう。

' ==============================================================================
' Script Name: DataCleansingEngine.vbs
' Description: 機種依存文字を検知し、安全な代替文字へ置換するデータクレンジングスクリプト
' Author: Senior Architect
' ==============================================================================

Option Explicit

' --- 設定エリア ---
Dim strTargetFolder, strOutputFile
strTargetFolder = "C:\Temp\Input"      ' 読み込み対象フォルダ
strOutputFile   = "C:\Temp\Output\cleansed_data.txt" ' 出力先ファイル

' --- メイン処理 ---
Call Main()

Sub Main()
    Dim fso, objStream, strContent, strCleanedContent
    Dim dictMapping
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    ' 1. フォルダの存在確認 (FSOの役割)
    If Not fso.FolderExists(strTargetFolder) Then
        WScript.Echo "Error: 対象フォルダが見つかりません。"
        WScript.Quit
    End If

    ' 2. 置換ルールの定義 (Dictionaryオブジェクトを使用)
    ' ここに「危険な文字」と「安全な文字」のペアを登録します
    Set dictMapping = CreateObject("Scripting.Dictionary")
    Call AddMapping(dictMapping)

    ' 3. ファイルの読み込み (ADODB.Streamの役割: Unicode/UTF-8を安全に扱うため)
    ' 今回は例として、フォルダ内の最初のテキストファイルを対象にします
    Dim targetFile
    targetFile = GetFirstFile(fso, strTargetFolder, "*.txt")
    
    If targetFile = "" Then
        WScript.Echo "対象ファイルが見つかりませんでした。"
        WScript.Quit
    End If

    WScript.Echo "Processing: " & targetFile

    ' ADODB.Streamを使用して、文字化けを防ぎつつ読み込む
    Set objStream = CreateObject("ADODB.Stream")
    objStream.Type = 2 ' adTypeText
    objStream.Charset = "UTF-8" ' 元ファイルがUTF-8の場合。Shift_JISなら "shift_jis"
    objStream.Open
    objStream.LoadFromFile targetFile
    strContent = objStream.ReadText
    objStream.Close

    ' 4. クレンジング実行 (文字の置換プロセス)
    strCleanedContent = CleanseText(strContent, dictMapping)

    ' 5. 結果の書き出し (ADODB.Streamを使用して安全に保存)
    objStream.Open
    objStream.Charset = "shift_jis" ' システム連携用にShift_JISで出力
    objStream.WriteText strCleanedContent
    objStream.SaveToFile strOutputFile, 2 ' adSaveCreateOverWrite
    objStream.Close

    WScript.Echo "完了しました。出力先: " & strOutputFile
    
    ' オブジェクトの解放 (メモリ管理の基本)
    Set dictMapping = Nothing
    Set objStream = Nothing
    Set fso = Nothing
End Sub

' --- サポート関数群 ---

' 置換リストの登録
Sub AddMapping(ByRef dict)
    ' 丸数字の置換
    dict.Add "①", "(1)"
    dict.Add "②", "(2)"
    dict.Add "③", "(3)"
    ' 特殊記号の置換
    dict.Add "㍉", "mm"
    dict.Add "㌔", "kg"
    dict.Add "㌘", "g"
    ' 必要に応じてここに追加していく
End Sub

' テキスト内の文字を辞書に基づいて置換する
Function CleanseText(ByVal text, ByRef dict)
    Dim key
    For Each key In dict.Keys
        ' Replace関数を使用して、見つかった機種依存文字を安全な文字へ
        text = Replace(text, key, dict(key))
    Next
    CleanseText = text
End Function

' フォルダ内の最初のファイルを取得する
Function GetFirstFile(fso, folderPath, pattern)
    Dim folder, file
    Set folder = fso.GetFolder(folderPath)
    For Each file In folder.Files
        ' 簡易的なパターンマッチング (実際はRegExpを使うとより高度)
        If InStr(file.Name, ".txt") > 0 Then
            GetFirstFile = file.Path
            Exit Function
        End If
    Next
    GetFirstFile = ""
End Function

4. コードの深層:プロの視点

このコードには、初学者が「なんとなく」で書くコードとは異なる、3つの重要な設計思想が組み込まれています。

① Dictionaryによる「変換テーブル」の分離

置換ルールを `If` 文の羅列で書くのは、素人の仕事です。
`Scripting.Dictionary` を使い、「データ(変換ルール)」と「ロジック(置換処理)」を分離しています。これにより、新しい機種依存文字が増えても、`AddMapping` 関数に一行追加するだけで済み、メインのロジックを汚さずにメンテナンスが可能です。

② ADODB.Streamによる「文字コードの橋渡し」

ここが最大のポイントです。
`FSO.OpenTextFile` を使うと、読み込みの時点で文字化けが確定してしまいます。しかし、`ADODB.Stream` を使い、`Charset = “UTF-8″` と明示的に指定することで、「一旦、全ての文字を正しくメモリ上に展開する」ことができます。
展開された後は、メモリ上の文字列として安全に操作し、最後に `Charset = “shift_jis”` で「システムが理解できる形」に変換して書き出す。この「変換のレイヤー」を意識することが、プロの仕事です。

③ オブジェクトのライフサイクル管理

スクリプトの終わりに `Set … = Nothing` を記述しています。
VBScriptはガベージコレクション(自動メモリ解放)を備えていますが、大規模なバッチ処理や、長時間稼働するサーバー上で動かす場合、明示的にオブジェクトを解放する習慣をつけておくことは、メモリリークを防ぐための「エンジニアとしての嗜み」です。

5. まとめ:次なるステップへ

今回のスクリプトをマスターすれば、あなたはもう「文字化けに怯えるユーザー」ではありません。「データの整合性を守るゲートキーパー(門番)」です。

ここをクリアすれば、VBScriptの基本はバッチリですよ。

次に挑戦するなら、`RegExp` (Regular Expressions) オブジェクトを組み合わせてみてください。特定のパターン(例:全角数字を半角数字に一括変換するなど)をより高度に制御できるようになります。

自動化の道は奥が深いですが、一つひとつの「なぜ?」を解き明かしていけば、必ず景色が変わってきます。また次のレクチャーでお会いしましょう!

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