バイナリファイルに対して文字列と整数を読み書きする方法、struct/pickle/shelveモジュールを使ってバイナリファイルに各種データを読み書きする方法を1ページにまとめて紹介。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
ここでは本連載でこれまでに紹介してきたバイナリファイルの読み書きの方法をまとめる。詳しい解説はコード例の後で紹介しているリンクを参照してほしい。テキストファイルの読み書きについては「テキストファイルの読み書きまとめ」を参照されたい。
# 文字列のバイナリファイルへの書き込み
with open('test.bin', 'wb') as f:
s = 'ディープインサイダー'
b = s.encode() # 文字列もバイト列にエンコードする必要がある
f.write(b) # バイナリファイルにはバイト列しか渡せない
# 文字列のバイナリファイルからの読み込み
with open('test.bin', 'rb') as f:
b = f.read()
s = b.decode()
print(s) # ディープインサイダー
# 整数のバイナリファイルへの書き込みと読み込み
from sys import byteorder
print(byteorder) # littleもしくはbig
length = 4 # 4バイト長整数に変換する
with open('test.bin', 'wb') as f:
n = 123456
b = n.to_bytes(length, byteorder) # nを4バイト長の符号なし整数に変換
f.write(b)
# 整数のバイナリファイルからの読み込み
with open('test.bin', 'rb') as f:
b = f.read(length) # lengthだけバイナリファイルから読み込み
n = int.from_bytes(b, byteorder) # バイト列を整数に変換する
print(f'read data: {n}') # read data: 123456
# 整数リストのバイナリファイルへの書き込みと読み込み
nlist = [1, 2, 3, 4, 5, 6]
length = 4 # 4バイト長整数
with open('test.bin', 'wb') as f:
# 整数リストをバイト列リストに変換してファイルに書き込み
blist = [n.to_bytes(length, byteorder) for n in nlist]
f.writelines(blist)
# 整数リストをバイト列に変換してファイルに書き込み
#b = b''.join([n.to_bytes(length, byteorder) for n in nlist])
#f.write(b)
# バイナリファイルからの整数の連続読み込み
with open('test.bin', 'rb') as f:
result = []
b = f.read(length) # lengthだけバイナリファイルから読み込み
while b: # データがあるだけ以下を繰り返す
n = int.from_bytes(b, byteorder) # 読み込んだデータを整数に変換
result.append(n) # リストに追加
b = f.read(length) # lengthだけバイナリファイルから読み込み
print(result) # [1, 2, 3, 4, 5, 6]
# バイト列を読み込んだ後にmemoryviewオブジェクトを得て、型変換を行う
with open('test.bin', 'rb') as f:
b = f.read()
mv = memoryview(b)
result = mv.cast('i').tolist()
print(result) # [1, 2, 3, 4, 5, 6]
バイナリファイルに対する読み書きについては「バイナリファイルを読み書きするには:文字列と整数編」を参照のこと。
# structモジュールを使ってバイナリファイルに書き込み
from struct import pack, unpack, calcsize, iter_unpack
person = ('かわさき', 120, 99.9)
fmt = '20sid' # 長さ20のバイト列(20s)、整数(i)、倍精度浮動小数点(d)
b = pack(fmt, person[0].encode(), person[1], person[2]) # fmtに従ってバイト列化
with open('data.bin', 'wb') as f:
f.write(b)
# データサイズの計算
data_size = calcsize(fmt)
print(data_size) # 32(このデータは32バイト長)
# バイナリファイルから読み込んで、structモジュールを使って復元
with open('data.bin', 'rb') as f:
b = f.read(data_size)
data = unpack(fmt, b)
data = (data[0].strip(b'\x00').decode(), data[1], data[2])
print(data) # ('かわさき', 120, 99.9)
# pathlibモジュールを使う
from pathlib import Path
p = Path('data2.bin')
b = pack(fmt, person[0].encode(), person[1], person[2])
p.write_bytes(b)
b = p.read_bytes()
data = unpack(fmt, b)
data = (data[0].strip(b'\x00').decode(), data[1], data[2])
print(data) # ('かわさき', 120, 99.9)
# 複数のデータをバイナリファイルに書き込み
p_list = [('かわさき', 120, 99.9),
('えんどう', 60, 68.3),
('いっしき', 25, 65.2)]
fmt = '20sid'
with open('data.bin', 'wb') as f:
b = [pack(fmt, p[0].encode(), p[1], p[2]) for p in p_list]
f.writelines(b)
# 複数のデータをバイナリファイルから読み込み
data_size = calcsize(fmt)
with open('data.bin', 'rb') as f:
b = f.read()
result = [(d[0].strip(b'\x00').decode(), d[1], d[2]) for d in iter_unpack(fmt, b)]
print(result)
書式指定文字 | Pythonのデータ型 | Cのデータ型 | サイズ |
---|---|---|---|
x | パディング | − | − |
c | 長さ1のバイト列 | char | 1 |
b | 整数 | signed char | 1 |
B | 整数 | unsigned char | 1 |
i | 整数 | int | 4 |
I | 整数 | unsigned int | 4 |
f | 浮動小数点数 | float | 4 |
d | 浮動小数点数 | double | 8 |
s、p | 文字列をバイト列に変換したもの | char[] | − |
structモジュールで使われる書式指定文字(抜粋) |
structモジュールを使ったバイナリファイルの読み書きについては「バイナリファイルを読み書きするには:structモジュール編」を参照のこと。
Copyright© Digital Advantage Corp. All Rights Reserved.