仕事でバイナリファイルを読み込む必要が出てきたんだけど、エディタで中身見れないし、読み込ませるプログラムも書けないし、マジでヤバいんだけど。。
バイナリファイルの処理は、プログラム初心者がつまづきやすい箇所かと思いますが、理解すればどうという事はありません。ただ1バイトのデータ(0~255)が連綿と並んでいるだけです。
私もプログラミングが不慣れな時代に、上司から独自フォーマットの顧客バイナリファイルを渡されて対応を丸投げされた時は、正直泣きそうになった記憶があります。
現在はググればいくらでも情報が出来てきますが、それでもプログラム初心者がぱっと見で使えそうな記事は少ない印象でした。
本記事は、当時の自分が読んでも理解出来る内容を目標としています。
そもそもバイナリファイルって何? という方は次の記事が参考になるかもです。
Pythonで簡単にバイナリファイルを読み込ませる方法
Pythonスクリプトで読み込ませるバイナリファイル
まずは次のPythonスクリプトを実行して、この記事で扱うバイナリファイルを作成してください。
f = open(r"C:\Python_source\02_BinaryFile\SampleBinary.bin","wb")
for i in range(32):
f.write(i.to_bytes(1,"big"))
f.close()
1行目のファイルのパスは、必要に応じて変更をお願いします。
作成したバイナリファイルをバイナリエディタで確認すると、下記のようになっているかと思います。
”ADDRESS” が “0” で値が”00″のデータが、アドレスが+1されるたびに+1されて、最後の32個目のデータは “1F(10進数で31)” となっています。
では早速、このバイナリファイルをPythonで読み込んでみましょう。
バイナリファイルを読み込むPythonスクリプトと実行結果
f = open(r"C:\Python_source\02_BinaryFile\SampleBinary.bin","rb") # バイナリファイル読み込み。
tmp = f.read() # ファイルの中身をread()メソッドで一気に読み込み。
for idx in range(len(tmp)): # ファイルのバイト数をlen()で取り出して、その回数for文で回す、
print (tmp[idx]) # 1バイトづつデータを出力
Pythonスクリプトの解説
1行目の
f = open(r”C:\Python_source\02_BinaryFile\SampleBinary.bin”,”rb”)
は、ファイルをバイナリモードで開いているだけです。
バイナリモードって何?という方は、次の記事をご参照ください。
2行目では、ファイルオブジェクトfをread()メソッドでアクセスする事で、ファイル中のバイトデータ全てを変数tmpへ代入しています。
この時 tmpはbytes型の変数となります。変数のデータ型は、変数をtype()関数へ引数として与える事ですぐに確認出来ます。
またPythonのインタラクティブモードでtmpの中身を確認すると、1バイト毎にバックスラッシュで区切られたデータを確認する事が出来ます。
>> type(tmp)
<class 'bytes'> # 変数の方はバイト型
>>> tmp
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f'
変数9バイト目のデータが “\t”, 10バイト目のデータが “\n” とおかしな値となっていますが、これはASCIIコード表の文字が、表示の都合で見えてしまっているだけです。共に特殊文字で、”\t” はタブを、”\n” は改行を示しています。
>>> tmp[8]
8
>>> tmp[9]
9
>>> tmp[10]
10
>>> type(tmp[10])
<class 'int'>
>>>
9バイト目と10バイト目のデータをインタラクティブモードでtmp[9]といった感じでダイレクトに確認すると、想定した値が格納されている事、またtype()で確認する事で各バイトデータは、int(整数)型で取り出される事も分かります。
3行目はファイルのバイト数をlen()で取り出して、その回数for文で回しています。len()の戻り値は32なので、idxには0から31までの整数が代入されたものが、4行目で実行される事となります。4行目のprint(tmp(idx)) はidxの値を変えながら、32回実行される事となります。
Pythonで読み込ませたデータを加工して出力する
途中で確認したように、tmp[idx]で取り出せる値はint型でした。なのでバイナリファイルから読み出した値を、4行目でプラス100してから出力する事も簡単に出来ます。
f = open(r"C:\Python_source\02_BinaryFile\SampleBinary.bin","rb")
tmp = f.read()
for idx in range(len(tmp)):
add = tmp[idx]+100
print (add)
print() で標準出力をするのではなくバイナリファイルとして保存すれば、元ファイルから加工したバイナリファイルを作る事が可能です。バイナリファイルの書き込みは、次回の記事で解説したいと思います。
最後まで読んで頂き、ありがとうございました。