web-dev-qa-db-ja.com

Pythonバイナリを書く

python 3を使用します。r+ bを使用して、ファイルにバイナリを書き込もうとしました。

for bit in binary:
    fileout.write(bit)

ここで、バイナリは数字を含むリストです。これをバイナリでファイルに書き込むにはどうすればよいですか?

終了ファイルはb 'x07\x08\x07 \のように見える必要があります

ありがとう

12
Alon

バイナリモードでファイルを開く場合、基本的に bytes タイプで作業しています。したがって、ファイルに書き込むときはbytesオブジェクトを渡す必要があり、ファイルから読み取るときはbytesオブジェクトを取得します。対照的に、ファイルをテキストモードで開くときは、strオブジェクトを使用します。

したがって、「バイナリ」を記述することは、実際にはバイト文字列を記述することです。

with open(fileName, 'br+') as f:
    f.write(b'\x07\x08\x07')

実際の整数をバイナリとして書きたい場合は、bytes関数を使用して整数のシーケンスをバイトオブジェクトに変換できます。

>>> lst = [7, 8, 7]
>>> bytes(lst)
b'\x07\x08\x07'

これを組み合わせて、バイナリモードで開かれたファイルにバイトオブジェクトとして整数のシーケンスを書き込むことができます。


Hyperboreusがコメントで指摘したように、bytesは実際に1バイトに収まる数字のシーケンス、つまり0〜255の数字のみを受け入れます。任意の(正の)整数をそのまま格納する場合、それらの正確なサイズ(これはstructに必要です)を知ることを気にせずに、それらの数値を別々のバイトに分割するヘルパー関数を簡単に書くことができます:

def splitNumber (num):
    lst = []
    while num > 0:
        lst.append(num & 0xFF)
        num >>= 8
    return lst[::-1]

bytes(splitNumber(12345678901234567890))
# b'\xabT\xa9\x8c\xeb\x1f\n\xd2'

したがって、数値のリストがある場合は、それらを簡単に反復処理してファイルに書き込むことができます。後で数値を個別に抽出する場合は、おそらく、個々のバイトがどの数値に属しているかを追跡する何かを追加する必要があります。

with open(fileName, 'br+') as f:
    for number in numbers:
        f.write(bytes(splitNumber(number)))
32
poke

ここで、バイナリは数字を含むリストです

数値には、千と一の異なるバイナリ表現(エンディアンネス、幅、1補数、2補数、異なる精度の浮動小数点数など)を含めることができます。そのため、まず、どの表現で数字を保存するかを決定する必要があります。次に、 struct モジュールを使用してそうすることができます。

たとえば、バイトシーケンス0x3480は32820(リトルエンディアン符号なしショート)、または-32716(リトルエンディアン符号付きショート)または13440(ビッグエンディアンショート)として解釈できます。

小さな例:

#! /usr/bin/python3

import struct

binary = [1234, 5678, -9012, -3456]
with open('out.bin', 'wb') as f:
    for b in binary:
        f.write(struct.pack('h', b)) #or whatever format you need

with open('out.bin', 'rb') as f:
    content = f.read()
    for b in content:
        print(b)
    print(struct.unpack('hhhh', content)) #same format as above

プリント

210
4
46
22
204
220
128
242
(1234, 5678, -9012, -3456)
13
Hyperboreus