我想附加一个我计算到现有二进制文件的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
有什么建议吗?
答案 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))