关于二进制文件的一般问题

8 投票
6 回答
2193 浏览
提问于 2025-04-16 14:28

我还是个初学者,对二进制文件有点困惑。当我在Python中以二进制模式写文件时,我写的其实只是普通文本,感觉没有什么二进制的东西。我知道我电脑上的每个文件都是二进制文件,但我还是搞不清楚我自己用二进制模式写的文件和那些像音频、视频等文件有什么区别,后者在文本编辑器里打开时会显示一堆乱码。

那些显示乱码的文件是怎么创建的呢?能不能给我一个小文件的例子,最好是用Python写的?

我觉得我问的问题可能很傻,但我真的很想知道。网上查了也没找到答案。

6 个回答

3

所谓的“文本”文件其实就是遵循某些规则的文件:这些文件里的字节通常是所有可能字节的一部分,通常是ASCII或Unicode值,并且这些字节会被组织成“行”,每行的结束有“行结束符”。不同的平台有不同的标准行结束符——Unix用的是\n,Mac用的是\r,而Windows用的是\r\n。所以,处理这些文件时需要根据情况进行转换。对于文本文件来说,这样处理是没问题的,但如果是其他类型的文件,比如音频文件,里面的0x0a\n)字节就不适合被转换成0x0d 0x0a\r\n)。当然,如果你一直在用Unix系统,这个问题可能就不会出现。

在Python 3中,所有字符串都是Unicode格式,打开一个文件作为文本时,你需要读写Unicode字符串,并且可能需要指定编码(默认是UTF-8)。而如果你打开一个文件作为二进制文件,就需要使用bytes对象,这些对象就是简单的8位字节列表,不会被编码。

这样解释清楚了吗?

4

当我以二进制模式写入文件时(在Python中),我只是写普通的文本。

当你升级到Python 3.x时,你需要改变一下写法:

>>> f = open(filename, 'wb')
>>> f.write("Hello, world!\n")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be bytes or buffer, not str
>>> f.write(b"Hello, world!\n")
14

不过你的问题其实不是关于二进制文件,而是关于 str 的。

在Python 2.x中,str 是一个字节序列,它有两种含义:

  • 一种是非Unicode字符串,或者
  • 原始的二进制数据(比如图像中的像素)。

如果你把后者当成前者来打印,就会得到一堆乱码。

Python 3.x 通过引入一个单独的 bytes 类型来处理二进制数据,解决了这种双重含义的问题,使得 str 明确表示为文本字符串(并且变成了Unicode)。

4

这是对你问题的直接回答:

import struct
with open('gibberish.bin', 'wb') as f:
    f.write(struct.pack('<4d', 3.14159, 42.0, 123.456, 987.654))

这段代码是把四个浮点数打包成一种二进制格式(小端格式的IEEE 756 64位浮点数)。

以下是你需要了解的一些内容:

以二进制模式读取和写入文件时,数据不会发生任何变化。相比之下,文本模式下,读取或写入的数据会根据平台的“文本文件”约定进行转换,包括任何Unicode的编码和解码。

在Unix/Linux/Mac OS X系统中:数据没有变化

在旧版Mac中:行分隔符是\r,会被转换为Python标准的\n

在Windows系统中:行分隔符是\r\n,会被转换为\n。还有一个不太为人知的事实是,Ctrl-Z也就是\x1a被视为文件结束,这个约定源自CP/M,它记录文件大小是用的128字节扇区的数量。

撰写回答