Windows上python中的二进制和文本I / O之间的区别

我知道我应该使用"rb"而不是"r"来打开一个二进制文件,因为Windows对于二进制和非二进制文件的行为不同。

但是我不明白,如果我以错误的方式打开一个文件,为什么这个区别甚至是必要的。 其他操作系统似乎通过处理这两种文件相同的罚款。

这个模式是关于换行的结尾。

在文本模式下阅读时,平台的本机行结束符(Windows上的\r\n )被转换为Python的Unix风格\n行尾。 在文本模式下书写时,会发生相反的情况。

在二进制模式下,没有这样的转换完成。

其他平台通常在没有转换的情况下可以很好地工作,因为它们本身存储行结束符\n 。 (Mac OS是一个例外,过去曾经使用过\r )。但是,依赖于此的代码是不可移植的。

那么这是为了历史(或者我喜欢说, 歇斯底里 )的原因。 文件打开模式是从C stdio库继承而来的,因此我们遵循它。

对于Windows,文本和二进制文件没有区别,就像在任何Unix克隆中一样。 不,我的意思是! – 有文件系统/操作系统,其中的文本文件与目标文件是完全不同的,等等。 在一些你必须提前指定最大长度的行和固定大小的记录被使用… 80列纸打孔卡等时代的化石。 幸运的是,在Unices,Windows和Mac中不是这样。

然而,所有其他的东西都是相同的 – Unix,Windows和Mac在输出流中使用什么字符来标记一行(或者是同一行,即行之间的分隔符)的结尾。 在Unix中,使用\ x0A(\ n)。 在Windows中,使用两个字符\ x0D \ x0A(\ r \ n)的顺序; 在Mac上 – 只要\ xod(\ r)。 下面是使用这两个符号的一些线索 – ASCII代码10被称为换行符(LF) ,当发送到电传打字机时,将导致它向下移动一行(Y ++),而不改变其水平(X)位置。 回车(CR) – ASCII 13 – 另一方面,将导致打印托架返回到行的开始(X = 0),而不滚动一行。 因此,在将输出发送到打印机时,必须发送\ r和\ n,以便滑架移动到新行的开头。 现在,当在终端键盘上打字时,操作员自然要按一个键而不是两个键结束。 对苹果公司而言,是关键的'Return'(\ r)。

无论如何,这是事情的结局。 C的创建者担心可移植性 – Unix中的大部分都是用C编写的,与以前不同的是,当使用汇编编写操作系统时。 所以他们不想处理每个平台上文本表示的怪癖,所以他们根据平台将这个恶意代码添加到他们的I / O库中,那个文件的输入和输出将被“修补”,以便程序会看到新的行是正义的 ,Unix方式 – 作为'\ n' – 无论是从Windows的'\ r \ n'还是从Mac的'\ r'。 所以开发者不必担心程序运行的是什么操作系统,它仍然可以读取和写入原生格式的文本文件。

然而,有一个问题 – 并不是所有的文件都是文本,还有其他的格式,而且它们对于用另一个字符替换一个字符非常敏感。 所以他们,我们会调用这些“二进制文件”,并指出通过在模式中包含“b”来fopen() ,这将标记库不做任何幕后转换。 这就是它的方式:)

因此,回顾一下,如果文件在二进制模式下以“b”打开,则不会发生转换。 如果它是以文本模式打开的,则根据平台的不同,可能会发生一些新行字符的转换 – 朝向Unix的角度。 自然,在Unix平台上,读写​​“文本”或“二进制”文件没有区别。

在Windows中,文本模式会将换行符\n转换为一个回车符,后跟一个换行符\r\n

如果您以二进制模式阅读文本,则没有问题。 如果您在文本模式下读取二进制数据,它可能会损坏。

阅读文件应该没有区别。 当写入文本文件时,Windows将自动弄乱你的换行符(它会在\n之前加\r )。 这就是为什么你应该使用"wb"