【问题标题】:Appending data bytes to binary file with Python使用 Python 将数据字节附加到二进制文件
【发布时间】:2014-01-04 11:42:16
【问题描述】:

我想将我计算出来的 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

有什么建议吗?

【问题讨论】:

  • 您正在以 binary 模式打开文件,但正在尝试写入 text 字符串。你需要先为字符串选择一个编码,或者写一些其他的二进制数据。

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


【解决方案1】:

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

&gt; 表示大端,I 表示无符号 4 字节整数。所以,这会返回同样的东西。在这两种情况下,你得到的是b'\x55\x66\x77\x88'(或者,就像Python 那样repr 它,b'\Ufw\x88')。


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

【讨论】:

  • 你可以在 Python 3.2+ 中使用binascii.crc32(filedata).to_bytes(4, byteorder='big')
  • @J.F.Sebastian:好吧,我可能也会使用明确的signed=False,但除此之外,是的,这要简单得多。我已经忘记了 3.2 和它。谢谢!
  • 我同意。尽管 binascii.crc32() 被记录为返回无符号整数并且 signed=False 是默认值,但显式的 signed=False 使您在 6 个月内更容易阅读,然后您就忘记了。
【解决方案2】:

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

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

然后可以通过转换为字节数组将 CRC 写入文件,如下所示:

filename.write(bytearray(serialized_crc))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 2011-12-11
    • 2019-03-31
    • 2020-10-07
    • 1970-01-01
    • 2013-05-13
    • 2012-08-31
    相关资源
    最近更新 更多