使用Python将数据字节附加到二进制文件

时间:2013-12-16 22:01:33

标签: python file python-3.x append crc

我想附加一个我计算到现有二进制文件的crc。

例如,crc是0x55667788。

我想将0x55,0x66,0x77和0x88附加到文件的末尾。

例如,如果我在HexEdit中打开文件,则该文件的最后四个字节 将显示0x55667788。

到目前为止,这是我的代码:

fileopen = askopenfilename()
filename = open(fileopen, 'rb+')
filedata = filename.read()
filecrc32 = hex(binascii.crc32(filedata))
filename.seek(0,2)
filename.write(filecrc32)
filename.close()

我收到以下错误:

File "C:\Users\cjackel\openfile.py", line 9, in <module>
filename.write(filecrc32)
TypeError: 'str' does not support the buffer interface

有什么建议吗?

2 个答案:

答案 0 :(得分:4)

hex函数返回字符串。在这种情况下,你有一个10个十六进制字符的字符串代表你的4字节数字,如下所示:

'0x55667788'

在Python 2.x中,您可以将这个不正确的数据写入二进制文件(它将显示为10个字节30 78 35 35 36 36 37 37 38 38,而不是您想要的四个字节55 66 77 88) 。 Python 3.x更智能,只允许您将bytes(或bytearray或类似的)写入二进制文件,而不是str


这里你想要的不是十六进制字符串,而是实际的字节数。

您描述所需字节的方式称为big-endian order。在大多数计算机上,“本机”订单是相反的小端,它会为您提供0x88776655而不是0x55667788

在Python 3.2+中,最简单的方法是使用int.to_bytes方法:

filecrc = binascii.crc32(filedata).to_bytes(4, byteorder='big', signed=False)

signed=False并不是必需的,因为它是默认值,但它是明确表示你肯定在处理无符号32位整数的好方法。)

如果您遇到早期版本,可以使用struct模块:

filecrc = struct.pack('>I', binascii.crc32(filedata))

>表示big-endian,I表示无符号4字节整数。所以,这会返回相同的东西。在任何一种情况下,你得到的是b'\x55\x66\x77\x88'(或者,正如Python repr b'\Ufw\x88'}。


错误有点神秘,因为没有新手会知道“缓冲接口”是什么(特别是因为3.x文档称之为Buffer Protocol,并且它只记录为部分CPython的C扩展API ...),但实际上它意味着你需要一个bytes-like object。通常,此错误意味着您只是忘记将字符串编码为UTF-8或其他编码。但是当你试图编写实际的二进制数据而不是编码文本时,它就是同样的错误。

答案 1 :(得分:0)

您需要序列化数据。序列化是获取的过程 整数的相关字节。在您的情况下,您的CRC是一个 4字节数。可以将单个4个字节检索到列表,如下所示:

serialized_crc = [(filecrc32 >> 24) & 0xFF,(filecrc32 >> 16) & 0xFF,
                 (filecrc32 >> 8) & 0xFF,filecrc32 & 0xFF]

然后可以通过转换为如下的bytearray将CRC写入文件:

filename.write(bytearray(serialized_crc))