技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

C#:バイナリファイルのデータを置換するツール

文字列置換はサクラエディタを使用すると楽ですが、サクラエディタを使用した場合は大量データの処理ができないという問題があります。
 
そこで、C#をプログラムにより置換を行うというのが有効になります。
プログラムでのファイルのストリーム読み込みであれば、高速に処理することができ、大量データにも対応することができます。
また、C#コンパイラはWindowsOSに標準で搭載されているので、環境設定が不要なのも便利な点です。
 
サンプルコードは以下です。
サンプルコードでは文字列の"hoge"を"fuga"に変換しているだけですが、バイナリファイルとして読み書きしている上に変換する文字は16進コードで指定しているため、ASCII文字以外の置換にも対応可能です。
また、ロジックを書き変えれば、より複雑な条件での置換も可能になります。
 
【フォルダ構成】
execute.bat
replace.cs
files─input.txt
 
ソースコード
・execute.bat
@echo off

C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe replace.cs
replace.exe
del replace.exe

pause
 
・replace.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Program
{
    class Program
    {
        static void Main(string[] args)
        {
            // ファイルオープン
            BinaryReader br = new BinaryReader
                (new FileStream(@"files\input.txt", FileMode.Open));
            BinaryWriter bw = new BinaryWriter
                (new FileStream(@"files\output.txt", FileMode.Create));
            
            try
            {
                int state = 0; // 0…初期状態
                               // 1…"h"を読みこんだ状態
                               // 2…"ho"を読みこんだ状態
                               // 3…"hog"を読みこんだ状態
                const byte Byte_h = (byte)0x68; // "h"の文字コード
                const byte Byte_o = (byte)0x6F; // "o"の文字コード
                const byte Byte_g = (byte)0x67; // "g"の文字コード
                const byte Byte_e = (byte)0x65; // "e"の文字コード
                const byte Byte_f = (byte)0x66; // "f"の文字コード
                const byte Byte_u = (byte)0x75; // "u"の文字コード
                const byte Byte_a = (byte)0x61; // "a"の文字コード
                ArrayList tmpDataList = new ArrayList(); // 読込文字の一時保存
                
                for (;;)
                {
                    // 1バイト読み込む
                    byte data = br.ReadByte();
                    
                    // stateが0、かつ読み込んだ文字が"h"の場合
                    if (state == 0 && data == Byte_h)
                    {
                        state = 1;
                        tmpDataList.Add(data);
                    }
                    // stateが1、かつ読み込んだ文字が"o"の場合
                    else if (state == 1 && data == Byte_o)
                    {
                        state = 2;
                        tmpDataList.Add(data);
                    }
                    // stateが2、かつ読み込んだ文字が"g"の場合
                    else if (state == 2 && data == Byte_g)
                    {
                        state = 3;
                        tmpDataList.Add(data);
                    }
                    // stateが3、かつ読み込んだ文字が"e"の場合
                    else if (state == 3 && data == Byte_e)
                    {
                        // "fuga"を出力
                        bw.Write(Byte_f);
                        bw.Write(Byte_u);
                        bw.Write(Byte_g);
                        bw.Write(Byte_a);
                        
                        // 一時保存した文字を消し、stateを元に戻す
                        tmpDataList.Clear();
                        state = 0;
                    }
                    // それ以外の場合
                    else
                    {
                        // 一時保存した文字と読み込んだ文字を出力
                        for (int i = 0; i<tmpDataList.Count; i++)
                        {
                            bw.Write((byte)tmpDataList[i]);
                        }
                        bw.Write(data);
                        
                        // 一時保存した文字を消し、stateを元に戻す
                        tmpDataList.Clear();
                        state = 0;
                    }
                }
            }
            
            //最後まで読んだらループを抜ける
            catch(EndOfStreamException)
            {
            }
            
            finally
            {
                br.Close();
                bw.Close();
            }
        }
    }
}
 
【入力ファイル】
・input.txt
    h ho hog hoge   12
3456
 
【出力ファイル】
・output.txt
    h ho hog fuga   12
3456