动态大小的二进制数据读写问题

0 投票
2 回答
3771 浏览
提问于 2025-04-16 08:28

我正在尝试以二进制模式从文件中读取数据,并对这些数据进行处理。

 try:
  resultfile = open("binfile", "rb")
 except:
  print "Error"
 resultsize = os.path.getsize("binfile")

文件开头有一个32字节的头部,我已经成功解析了它,然后就开始了二进制数据的缓冲区。数据的大小可以在16到4092字节之间,格式也可以是文本、PDF、图片或其他任何东西。头部里有数据的大小信息,所以我这样做:

contents = resultfile.read(resultsize)

这样就把整个文件放进了一个字符串缓冲区。我发现这可能是我的问题,因为当我尝试将“contents”中的十六进制数据块复制到新文件时,有些字节没有正确复制,导致PDF和图片文件损坏。

在解释器中打印出文件字符串缓冲区的一部分,结果像是"%PDF-1.5\r\n%\xb5\xb5\xb5\xb5\r\n1 0 obj\r\n",而我其实只想要字节本身,以便将它们写入新文件。有没有简单的解决办法我没想到呢?

这里有一个十六进制转储的例子,左边是我用Python写的PDF,右边是真正的PDF:

25 50 44 46 2D 31 2E 35 0D 0D 0A 25 B5 B5 B5 B5 0D 0D 0A 31 20 30 20 6F 62 6A 0D 0D 0A

25 50 44 46 2D 31 2E 35 0D    0A 25 B5 B5 B5 B5 0D    0A 31 20 30 20 6F 62 6A

似乎每当出现0D 0A时,就会添加一个0D。在图片文件中可能是不同的字节,我不太记得了,可能需要测试一下。我的代码写新文件的部分很简单,使用contents作为存放所有数据的字符串缓冲区。

        fbuf = contents[offset+8:size+offset]
        fl = open(fname, 'a')
        fl.write(fbuf)

这个过程是在一个循环中调用的,循环是根据头部中找到的特征来进行的。Offset+8是实际PDF数据的开始位置,size是要复制的块的大小。

2 个回答

0

你得到的结果 就是 "这些字节本身"。你可以把它们用 write() 函数写入一个打开的文件,这样就可以复制它们。

"听起来每当有一个 0D 0A 时,就会多加一个 0D"

这听起来像是你在使用 Windows 系统,并且你是以文本模式打开了你的某个文件,而不是以二进制模式。

2

你需要以二进制模式打开你的输出文件,就像你打开输入文件一样。否则,换行符可能会被改变。你可以在你的十六进制转储中看到这种情况:0A 字符(也就是 '\n')被改成了 OD 0A(也就是 '\r\n')。

这样做应该没问题:

input_file = open('f1', 'rb')
contents = input_file.read()

#....
data = contents[offset+8:size+offset] #for example

output_file = open('f2', 'wb')
output_file.write(data)

撰写回答