Pythonを使ったバイナリファイルの読み方を紹介します。
バイナリファイルを読み込む: open, read
バイナリファイルの読み込む場合は、テキストファイル同様にopen関数を使用し、モードを"rb"(read, binary)にします。
# 構文
# open("ファイルパス", "モード")
with open("./sample.bin", "rb") as f:
f_sample = f.read()
print(f_sample) # b'sample binary word.'
バイナリファイルを書き込みたい場合はモードを"wb"にし、テキストファイル同様にバイナリデータをwrite()で書き込めます。
(b"文字列"とすることでバイナリ型として書き込めます。)
with open("./sample.bin", "wb") as f:
f.write(b"sample binary word.")
フォーマットの決まったバイナリファイルを読み込む
バイナリファイルはフォーマット仕様が提供され、その仕様に沿って読み込むことがあります。ここでは、ctypes.Structureライブラリを使って以下の図のフォーマットで記載されたバイナリファイルを、読み込んでいきます。
データフォーマットを定義する
データフォーマットを定義するには、ctypes.Structureを継承したClassを作成します。
Classの中には、_fields_属性を作成し、フィールド名称とフィールド型をセットにしたタプルで記載していきます。
先ほどのデータフォーマットは以下のように記載されます。
import ctypes as c
# フォーマットを定義
class SampleFormat(c.Structure):
_fields_ = [
("id", c.c_uint32), # 符号なし32ビット整数型
("type", c.c_char*4), # 4バイトの文字型
("data", c.c_char*120) # 120バイトの文字型
]
ctypesには様々なデータ型が定義されており、一覧は公式リファレンスから確認できます。
データフォーマットの定義ができたので、ファイルへの書き込みと読み込みを行ってみます。
バイナリファイルの読み書き
データフォーマットの内容をバイナリファイルへ書き込んでいきます。
書き込む値はデータフォーマットのインスタンス作成時に、初期値として指定できます。
# データフォーマットに値を代入
format_data = SampleFormat(100, b'DATA', 'バイナリのサンプルデータ。'.encode())
# バイナリファイルに書き込み
with open("./binary_format.bin", "bw") as f:
f.write(format_data)
次に、バイナリファイルを読み込んでいきます。
読み込むまでの流れは次の2ステップになります。
- バイナリファイルを開く:open関数
- データフォーマットに代入:readintoメソッド
readintoメソッドを使うことで、事前に定義したフォーマットにバイナリデータを代入することができます。
with open("./format.bin", "rb") as f:
# 定義したフォーマットのインスタンスを作成
format_data = SampleFormat()
# ファイルを読み込み、フォーマットに代入
f.readinto(format_data) # 事前に要したバイナリデータの入れ物にデータを入れ込む
print(f'id: {format_data.id}') # 100
print(f'type: {format_data.type}') # b'DATA'
print(f'data: {format_data.data.decode()}') # バイナリのサンプルデータ。
書き込んだバイナリデータが読み込めていることが分かります。
ビッグエンディアン、リトルエンディアンの指定
バイトオーダー(ビッグエンディアン、リトルエンディアン)は、データフォーマットのClassを作成する際に、継承するClassを変更することで指定できます。
# ビッグエンディアンの場合
class BE_format(c.BigEndianStructure):
_fields_ = [
("id", c.c_uint32),
("type", c.c_char*4),
("data", c.c_char*120)
]
# リトルエンディアンの場合
class BE_format(c.LittleEndianStructure):
_fields_ = [
("id", c.c_uint32),
("type", c.c_char*4),
("data", c.c_char*120)
]
フォーマットのサイズを確認する
定義したデータフォーマットのサイズは、ctypes.Sizeofで確認できます。
print(c.sizeof(format_data)) # 128
コメント