連載
» 2021年06月22日 05時00分 公開

[解決!Python]バイナリファイルの読み書きまとめ解決!Python

バイナリファイルに対して文字列と整数を読み書きする方法、struct/pickle/shelveモジュールを使ってバイナリファイルに各種データを読み書きする方法を1ページにまとめて紹介。

[かわさきしんじ,Deep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

 ここでは本連載でこれまでに紹介してきたバイナリファイルの読み書きの方法をまとめる。詳しい解説はコード例の後で紹介しているリンクを参照してほしい。テキストファイルの読み書きについては「テキストファイルの読み書きまとめ」を参照されたい。

バイナリファイルの読み書き

# 文字列のバイナリファイルへの書き込み
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モジュールを使ったバイナリファイルの読み書き

# 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モジュール編」を参照のこと。

pickleモジュールを使ったバイナリファイルの読み書き

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。