NonSoft

バイナリファイルを比較し差分を表示するサンプル(C#.NET)


 サンプル(ソース/コード)
<このサンプルの概要>
バイナリファイルを比較し差分を分かりやすく表示するサンプル(C#.NET)です。

バイナリ差分表示結果の例
----------------------------------------------------------------------------
区分 NO file1                            NO file2
      1 31323334353637383930313233343536  1 31323334353637383930313233343536
変更  2 4142434445464748494A4B4C4D4E4F50  2 4142434445464720494A4B4C4D4E4F50
追加                                      3 6162636465666768696A6B6C6D6E6F70
----------------------------------------------------------------------------

処理の流れは以下の流れです。
1.バイナリファイル読み込み
2.バイナリデータを16進文字列に変換
3.バイナリ差分解析
4.バイナリ差分表示)

差分表示する必要が無い時(バイナリ比較のみ)は下の方にあるサンプルをご覧ください。
バイナリファイルを比較するだけのサンプル

VB6版   はこちら「バイナリファイルを比較し差分を表示するサンプル(VB6)」   です。
VB.NET版はこちら「バイナリファイルを比較し差分を表示するサンプル(VB.NET)」です。

バイナリファイルの比較が出来るツールがありますので紹介します。
テキスト差分表示ツールはテキストを比較するツールですがバイナリも比較出来ます。

ファイル比較関係のその他のツールやサンプルソースはこちらです。
ファイル比較/フォルダ比較

★2つのバイナリファイルを比較し差分をデバッグ出力するサンプル
// 2つのバイナリファイルを比較し差分をデバッグ出力するサンプル
// バイナリ差分表示結果の例
// 区分 NO file1                            NO file2
//       1 31323334353637383930313233343536  1 31323334353637383930313233343536
// 変更  2 4142434445464748494A4B4C4D4E4F50  2 4142434445464720494A4B4C4D4E4F50
// 追加                                      3 6162636465666768696A6B6C6D6E6F70
private void button1_Click(object sender, EventArgs e)
{
    // バイナリファイル読み込み
    Byte[] bytDt1;
    Byte[] bytDt2;
    bytDt1 = ByteRead(@"D:\Temp\Test1.txt");
    bytDt2 = ByteRead(@"D:\Temp\Test2.txt");

    // バイナリデータを16進文字列に変換
    String strDt1;
    String strDt2;
    strDt1 = ByteToString(bytDt1);
    strDt2 = ByteToString(bytDt2);
    strDt1 = strDt1.TrimEnd('\n');
    strDt2 = strDt2.TrimEnd('\n');

    // 16進文字列を行単位の配列に変換
    String[] strAr1;
    String[] strAr2;
    if (strDt1.Substring(strDt1.Length - 2, 2).Equals("\n"))
    {
        strDt1 = strDt1.Substring(0, strDt1.Length - 2);
    }
    strAr1 = strDt1.Split('\n');
    if (strDt2.Substring(strDt2.Length - 2, 2).Equals("\n"))
    {
        strDt2 = strDt2.Substring(0, strDt2.Length - 2);
    }
    strAr2 = strDt2.Split('\n');

    // バイナリ差分解析
    int num = strAr1.Length;
    if (num < strAr2.Length) num = strAr2.Length;
    String[,] dfList = new String[5, num + 1];
    dfList[0, 0] = "区分";
    dfList[1, 0] = "NO";
    dfList[2, 0] = "file1";
    dfList[3, 0] = "NO";
    dfList[4, 0] = "file2";
    for (int i = 1; i <= num; i++)
    {
        if (i - 1 <= strAr1.Length - 1)
        {
            dfList[1, i] = "" + i;
            dfList[2, i] = strAr1[i - 1];
        }
        if (i - 1 <= strAr2.Length -1)
        {
            dfList[3, i] = "" + i;
            dfList[4, i] = strAr2[i - 1];
        }
        if( dfList[2, i] == null && dfList[4, i] != "" ){
            dfList[0, i] = "追加";
        }
        else if (dfList[2, i] != "" && dfList[4, i] == null)
        {
            dfList[0, i] = "削除";
        }
        else if (dfList[2, i] != dfList[4, i])
        {
            dfList[0, i] = "変更";
        }
    }

    // バイナリ差分表示
    for (int i = 0; i <= dfList.GetLength(1) - 1; i++ )
    {
        System.Diagnostics.Debug.WriteLine(
            dfList[0, i] + "\t" +
            dfList[1, i] + "\t" + dfList[2, i] + "\t" +
            dfList[3, i] + "\t" + dfList[4, i]);
    }
}

// バイナリファイル読み込み
private Byte[] ByteRead(String fPath)
{
    Byte[] dt = new Byte[] { };
    System.IO.Stream sr = null;
    System.IO.BinaryReader br = null;
    sr = System.IO.File.Open(fPath,
        System.IO.FileMode.Open,
        System.IO.FileAccess.Read);
        br = new System.IO.BinaryReader(sr);
    dt = new Byte[sr.Length];
    br.Read(dt, 0, dt.Length);
    br.Close();
    sr.Close();
    return dt;
}

// バイナリデータを16進文字列に変換
public String ByteToString(Byte[] bytDt)
{
    const int LBYT = 16;
    System.Text.StringBuilder sb = new System.Text.StringBuilder("");
    for (int i = 0; i < bytDt.Length; i++)
    {
        int ival = bytDt[i];
        String sval;
        if (ival < 16)
        {
            sval = "0" + Convert.ToString(ival, 16);
        }
        else
        {
            sval = Convert.ToString(ival, 16);
        }
        sb.Append(sval);

        if (((i + 1) % LBYT) != 0)
        {
        }else{
            sb.Append("\n");
        }
    }
    return sb.ToString();
}

★2つのバイナリファイルを比較するだけのサンプル
private void button1_Click(object sender, EventArgs e)
{
    String fpath1 = @"D:\Temp\Test1.txt";
    String fpath2 = @"D:\Temp\Test2.txt";
    System.IO.FileInfo f1 = new System.IO.FileInfo(fpath1);
    System.IO.FileInfo f2 = new System.IO.FileInfo(fpath2);
    if (f1.Length != f2.Length)
    {
        MessageBox.Show("不一致");
        return;
    }

    System.IO.Stream sr1 = null;
    System.IO.Stream sr2 = null;
    System.IO.BinaryReader br1 = null;
    System.IO.BinaryReader br2 = null;
    sr1 = System.IO.File.Open(fpath1,
        System.IO.FileMode.Open,
        System.IO.FileAccess.Read);
    sr2 = System.IO.File.Open(fpath2,
        System.IO.FileMode.Open,
        System.IO.FileAccess.Read);
    br1 = new System.IO.BinaryReader(sr1);
    br2 = new System.IO.BinaryReader(sr2);

    Boolean dif = false;
    while (true)
    {
        int bytDt1;
        int bytDt2;
        bytDt1 = sr1.ReadByte();
        bytDt2 = sr2.ReadByte();
        // バイナリデータを比較
        if (bytDt1 != bytDt2)
        {
            dif = true;
            break;
        }
        if (bytDt1 == -1) break;
    }

    br1.Close();
    br2.Close();
    sr1.Close();
    sr2.Close();

    if (dif)
    {
        MessageBox.Show("バイナリデータ不一致");
    }
    else
    {
        MessageBox.Show("バイナリデータ一致");
    }
}