Python写二进制文件

17

我使用 Python 3,尝试将二进制数据写入文件时使用 r+b 模式。

for bit in binary:
    fileout.write(bit)

二进制是包含数字的列表,如何将其以二进制形式写入文件?

最终的文件应该看起来像 b' x07\x08\x07。

谢谢。


这里的“二进制”是什么意思?你想要1和0吗? - Wooble
可能是在Python中读写二进制文件的重复问题。 - Yuval Adam
2个回答

39
当你以二进制模式打开文件时,实际上是在使用 bytes 类型。因此,当你向文件写入时,需要传递一个 bytes 对象,而当你从中读取时,会得到一个 bytes 对象。相反,在文本模式下打开文件时,你将使用 str 对象。
因此,“二进制”写作的其实是一个 bytes 字符串:
with open(fileName, 'br+') as f:
    f.write(b'\x07\x08\x07')

如果您想将实际整数写成二进制形式,可以使用bytes函数将一系列整数转换为字节对象:

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

结合这个方法,你可以把一系列的整数作为 bytes 对象写入以二进制模式打开的文件中。


正如Hyperboreus在评论中指出的,bytes 只能接受介于0和255之间的数字序列,即一个字节范围内的数字。 如果你想以它们本来的方式存储任意(正)整数,而不必担心了解其确切大小(这对于结构体是必需的),那么你可以轻松地编写一个帮助函数,将这些数字拆分成单独的字节:

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)))

8
+1 但或许需要提到在Python 2.x中,openbytes的行为是不同的。 - wim
1
@wim OP说他们正在使用Python 3;现在已经将标签添加到问题中了。(猜想我们同时做到了^^) - poke
1
你在第一次打开时不应该使用"w+b"吗?(注意"w") - Nande
@poke,我刚刚测试了一下,在Python 2.7中,当文件不存在时,使用“r+”调用open将引发异常。我认为正确的使用方式是使用“rw+”,但这也会引发异常。 - Nande
2
@Nande r+ 的行为是有意的。并非所有打开模式都会在文件不存在时创建它。但这并不使 r+ 无效 ;) 另外,rw+ 不是有效的模式。请参阅文档以获取有关打开模式的更多信息。 - poke
显示剩余8条评论

14

二进制是一个包含数字的列表

一个数字可以有一千零一种不同的二进制表示(大小端、宽度、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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接