在 Python 中将二进制数据写入文件

Posted

技术标签:

【中文标题】在 Python 中将二进制数据写入文件【英文标题】:Writing binary data to a file in Python 【发布时间】:2014-09-29 20:59:09 【问题描述】:

我正在尝试将数据(文本、浮点数据)写入二进制文件,以便稍后由另一个程序读取。问题是这个程序(在 Fort95 中)非常特别。为了正确读取文件,每个字节都必须位于正确的位置。我尝试使用 Bytes 对象和 .encode() 进行写入,但运气不佳(我可以从文件大小看出它正在写入额外的数据字节)。我试过的一些代码:

mgcnmbr='42'
bts=bytes(mgcnmbr)
test_file=open(PATH_HERE/test_file.dat','ab')
test_file.write(bts)
test_file.close()

我也试过了:

mgcnmbr='42'
bts=mgcnmbr.encode(utf_32_le)
test_file=open(PATH_HERE/test_file.dat','ab')
test_file.write(bts)
test_file.close()

为了澄清,我需要的是整数值 42,写为 4 字节二进制。接下来,我会将数字 1 和 0 写入 4 字节二进制文件中。那时,我应该正好有 12 个字节。每个都是一个 4 字节的有符号整数,以二进制形式编写。我对 Python 很陌生,似乎无法解决。有什么建议? this 之类的东西?我需要完全控制每个整数(以及后来的 4 字节浮点数)的字节数。

谢谢

【问题讨论】:

查看标准库中的struct.pack ***.com/questions/29834047/… 【参考方案1】:

您需要struct 模块。

import struct

fout = open('test.dat', 'wb')

fout.write(struct.pack('>i', 42))
fout.write(struct.pack('>f', 2.71828182846))

fout.close()

struct.pack 中的第一个参数是格式字符串。

格式字符串中的第一个字符指示数据的字节顺序或endianness(最重要或最不重要的字节首先存储 - 大端或小端)。字节顺序因系统而异。如果“>”不起作用,请尝试“

格式字符串中的第二个字符是数据类型。不出所料,“i”代表整数,“f”代表浮点数。字节数由类型决定。例如,短裤或“h's”是两个字节长。还有无符号类型的代码。例如,“H”对应于无符号短。

struct.pack 中的第二个参数当然是要打包到字节对象中的值。

这是我告诉你我在几件事上撒谎的部分。首先我说字节数是由类型决定的。这只是部分正确。给定类型的大小在技术上取决于平台,因为 C/C++ 标准(结构模块所基于)仅指定 最小 大小。这将我引向第二个谎言。格式字符串中的第一个字符还编码是使用标准(最小)字节数还是使用本机(平台相关)字节数。 (“>”和“alignment数据。

documentation on the struct module 有格式字符串参数表。

您还可以将多个原语打包到一个字节对象中并实现相同的结果。

import struct

fout = open('test.dat', 'wb')

fout.write(struct.pack('>if', 42, 2.71828182846))

fout.close()

你当然可以使用 struct.unpack 解析二进制数据。

【讨论】:

这是正确的。只是一个额外的提示:使用with 语句以避免忘记close 当心,stought.pack 格式链中的符号 '>' 仅适用于大端系统,如摩托罗拉 68000 或 PowerPC G5,最好使用将创建本机格式 ( big- endian 或 little-endian),请注意,您将创建一个不能移植到其他平台的文件。【参考方案2】:

假设您希望它采用 little-endian,您可以执行以下操作以将 42 写入四字节二进制文件。

test_file=open(PATH_HERE/test_file.dat','ab')
test_file.write(b'\xA2\0\0\0')
test_file.close()

A2 是十六进制的 42,字节 '\xA2\0\0\0' 使第一个字节等于 42,后跟三个空字节。此代码写入字节:42, 0, 0, 0。

您的代码写入字节以表示 UTF 32 中的字符“4”,并写入字节以表示 UTF 32 中的 2。这意味着它写入字节:52、0、0、0、50、0、0、0 ,因为以 UTF 32 编码时,每个字符都是四个字节。

还有一个用于调试的十六进制编辑器可能对您有用,然后您可以看到程序正在输出的字节,而不仅仅是大小。

【讨论】:

是的,我知道发生的事情是将每个字符写入 UTF32 中的 4 字节值,这就是为什么我得到 8 个字节(当我使用小端序时)。但是,该程序主要用作转换器,它从文件中读取数据并将其以适当的二进制形式传输到另一个文件。这些文件非常庞大,其中写入了数十万行和值。所以我不能只为每个值输入十六进制形式。 chr(y&0xFF) + chr((y>>8)&0xFF) + chr((y>>(8*2))&0xFF) + chr((y>>(8*3))&0xFF) 应该适用于转换四字节整数,其中 y 是要转换为字符串的数字。它通过向下移动数字并逐个输入字节来工作。不过,我不知道如何处理浮点数。 -- 如果你知道你想要什么字节并且正在使用 python3,你可以使用bytes([<1st byte>, <2nd byte>, <3rd byte>, <4th byte>])。用你想要的字节替换 。【参考方案3】:

在我的问题Write binary string in binary file Python 3.4 我喜欢这样:

file.write(bytes(chr(int(mgcnmbr)), 'iso8859-1'))

【讨论】:

以上是关于在 Python 中将二进制数据写入文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PySide 和 Python 3.X 中将字节写入 QDataStream?

使用 python 将二进制数据写入 zip 文件

如何在 Python 3 中将原始十六进制字节写入标准输出?

将 00001010 写入 Qfile 会在前面添加另一个 Byte

在 JavaScript 中将字节解释为打包的二进制数据

Slave没有在mysql主从复制中将任何数据写入表中