Python:读写二进制数据

2024-05-16 09:22:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道有很多几乎相同的问题,但似乎没有真正针对一般情况。

所以假设我想打开一个文件,在内存中读取它,可能对相应的位字符串执行一些操作,然后将结果写回文件。

下面是我觉得很简单的,但是它会导致完全不同的输出。请注意,为了简单起见,我只在此处复制文件:

file = open('INPUT','rb')
data = file.read()
data_16 = data.encode('hex')
data_2 = bin(int(data_16,16))

OUT = open('OUTPUT','wb')

i = 0
while i < len(data_2) / 8:
    byte = int(data_2[i*8 : (i+1)*8], 2)
    OUT.write('%c' % byte)
    i += 1

OUT.close()

我看了datadata_16data_2。在我看来,这些转变是有意义的。

正如预期的那样,输出文件的大小与输入文件的大小完全相同。

编辑:我考虑过前导“0b”必须被剪切的可能性。请参见以下内容:

>>> data[:100]
'BMFU"\x00\x00\x00\x00\x006\x00\x00\x00(\x00\x00\x00\xe8\x03\x00\x00\xee\x02\x00\x00\x01\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x0b\x00\x00\x12\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05=o\xce\xf4^\x16\xe0\x80\x92\x00\x00\x00\x01I\x02\x1d\xb5\x81\xcaN\xcb\xb8\x91\xc3\xc6T\xef\xcb\xe1j\x06\xc3;\x0c*\xb9Q\xbc\xff\xf6\xff\xff\xf7\xed\xdf'
>>> data_16[:100]
'424d46552200000000003600000028000000e8030000ee020000010018000000000000000000120b0000120b000000000000'
>>> data_2[:100]
'0b10000100100110101000110010101010010001000000000000000000000000000000000000000000011011000000000000'
>>> data_2[1]
'b'

也许BMFU"部分应该从data中切下来?


Tags: 文件dataopenbyteoutfileintx00
3条回答

您可以简单地将数据变量写回原处,这样您就可以成功地进行往返旅行了。

但看起来您打算将文件作为一个由01字符组成的字符串来处理。这没什么问题(虽然很少有必要),但是您的代码采用了一种非常迂回的方式将数据转换为该表单。与其构建一个怪物整数并将其转换为位字符串,不如一次只对一个字节执行此操作:

data = file.read()
data_2 = "".join( bin(ord(c))[2:] for c in data ) 

data_2现在是一个0和1的序列。(在一个字符串中,与您拥有的字符串相同;但是如果您要进行更改,我会将位字符串保留在列表中)。反向转换也最好逐字节完成:

newdata = "".join(chr(int(byte, 8)) for byte in grouper(long_bitstring, 8, "0"))

这使用^{} documentation中的grouper配方。

from itertools import izip_longest
def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

您可以使用struct模块来读写二进制数据。(链接到文档here。)

编辑

对不起,我被你的头衔误导了。我只知道你是在文本文件中写二进制数据,而不是直接写二进制数据。

>>> bin(25)
'0b11001'

注意两件事:

  1. 开头的“0b”。这意味着你的切片将减少2位。

  2. 缺少8位的填充。这将损坏每次的数据,除非它与点1啮合。

一个字节一个字节地处理文件,而不是像这样一大口地处理它。如果你发现你的代码太慢了,那么你需要找到一种更快的逐字节工作的方法,而不是切换到一个不可修复的有缺陷的方法,比如这个方法。

相关问题 更多 >