Pythonその他

Pythonでバイナリファイルを比較してみた

Pythonには、様々なクラスや関数が用意されていて、その中には、2つのバイナリファイルを比較できるものも含まれている。

今回は、Pythonでバイナリファイルを比較し差分を出力してみたので、そのサンプルプログラムを共有する。

前提条件

以下の記事の、Anacondaのインストールが完了していること。

Python開発用のAnacondaをインストールしJupyter Notebookを利用してみた今回は、Pythonを勉強してみたいと思い、Python開発環境を構築してみたので、その手順を共有する。 Python開発用として...

また、実行するPythonのバージョンが以下であること。
前提条件

サンプルプログラムの作成

作成したサンプルプログラムの構成は、以下の通り。
サンプルプログラムの構成

バイナリファイルを作成するサンプルプログラムは以下の通りで、バイナリファイルにバイナリデータを書き込み、書き込んだ内容を確認している。

# バイナリファイルを定義
bin_test1 = 'test1.dat'
bin_test2 = 'test2.dat'
bin_test3 = 'test3.dat'

# バイナリファイルtest1.datを作成
f = open(bin_test1, 'wb')
b_array = bytearray([0x1b, 0x00, 0x18, 0x22, 0x3a, 0x16, 0x04, 0x26, 0x2f, 0x07])
f.write(b_array)
f.close()

# バイナリファイルtest2.datを作成
# 内容はtest1.datと同じとする
f = open(bin_test2, 'wb')
b_array = bytearray([0x1b, 0x00, 0x18, 0x22, 0x3a, 0x16, 0x04, 0x26, 0x2f, 0x07])
f.write(b_array)
f.close()

# バイナリファイルtest3.datを作成
# 内容はtest1.datと違うものとする
f = open(bin_test3, 'wb')
b_array = bytearray([0x1b, 0x00, 0x22, 0x3a, 0x17, 0x05, 0x26, 0x2f, 0x07, 0x14, 0x17])
f.write(b_array)
f.close()

# バイナリファイルtest1,test2,test3の内容を読み込む
f = open(bin_test1, 'rb')
data1 = f.read()
f.close()

f = open(bin_test2, 'rb')
data2 = f.read()
f.close()

f = open(bin_test3, 'rb')
data3 = f.read()
f.close()

print("*** バイナリファイルの内容をbytes型で表示 ***")
print("test1.dat : ")
print(data1)
print()
print("test2.dat : ")
print(data2)
print()
print("test3.dat : ")
print(data3)

また、バイナリファイルの差分を確認するサンプルプログラムは以下の通りで、バイナリファイルの差分有無や、バイナリファイルの差分内容を表示している。

import filecmp
import difflib

# バイナリファイルを定義
bin_test1 = 'test1.dat'
bin_test2 = 'test2.dat'
bin_test3 = 'test3.dat'

# バイナリファイルtest1,test2,test3の内容を読み込む
f = open(bin_test1, 'rb')
data1 = f.read()
f.close()

f = open(bin_test2, 'rb')
data2 = f.read()
f.close()

f = open(bin_test3, 'rb')
data3 = f.read()
f.close()

print("*** バイナリファイルの内容をbytes型で表示 ***")
print("test1.dat : ")
print(data1)
print()
print("test2.dat : ")
print(data2)
print()
print("test3.dat : ")
print(data3)
print()

# バイナリファイルを比較した結果
cmp_test1_test2 = filecmp.cmp(bin_test1, bin_test2, False)
cmp_test1_test3 = filecmp.cmp(bin_test1, bin_test3, False)

print("*** バイナリファイルの内容を比較した結果を表示(True:差分なし、False:差分あり) ***")
print("test1.datとtest2.datを比較した結果 : ")
print(cmp_test1_test2)
print()
print("test1.datとtest3.datを比較した結果 : ")
print(cmp_test1_test3)
print()

# バイナリファイルtest1,test2の差分を表示
s = difflib.SequenceMatcher(None, data1, data2)

print("*** バイナリファイルtest1.datとtest2.datの差分を表示(差分なし) ***")
for tag, i1, i2, j1, j2 in s.get_opcodes():
    print('{:7}  data1[{}:{}] --> data2[{}:{}] {!r:>8} --> {!r}'
             .format(tag, i1, i2, j1, j2, data1[i1:i2], data2[j1:j2]))
print()

# バイナリファイルtest1,test3の差分を表示
s = difflib.SequenceMatcher(None, data1, data3)

print("*** バイナリファイルtest1.datとtest3.datの差分を表示 ***")
for tag, i1, i2, j1, j2 in s.get_opcodes():
    print('{:7}  data1[{}:{}] --> data3[{}:{}] {!r:>8} --> {!r}'
             .format(tag, i1, i2, j1, j2, data1[i1:i2], data3[j1:j2]))



サンプルプログラムの実行結果

サンプルプログラムの実行結果は、以下の通り。

1) コマンドプロンプトを起動し、サンプルプログラムのある場所まで移動する。
サンプルプログラムの実行結果_1

2) pythonコマンドで「make_binary.py」を実行し、バイナリファイルを作成する。
サンプルプログラムの実行結果_2

3) 2)を実行後、以下のように、バイナリファイルが作成されていることが確認できる。
サンプルプログラムの実行結果_3

4) pythonコマンドで「diff_binary.py」を実行し、バイナリファイルを比較した結果を表示する。
サンプルプログラムの実行結果_4

以上より、2つのバイナリファイルの差分有無はfilecmpモジュールのcmp関数で、2つのバイナリファイルの差分内容はdifflibモジュールのSequenceMatcherクラスで、それぞれ確認できる。

要点まとめ

  • Pythonで、filecmpモジュールのcmp関数を利用すると、2つのバイナリファイルの差分有無を確認できる。
  • Pythonで、difflibモジュールのSequenceMatcherクラスを利用すると、2つのバイナリファイルの差分内容を確認できる。