简短回答

简短回答

在许多不同的编程语言中,都有专门的构造来解决 Windows 区分文本和二进制文件这一事实。

例如,在 Ruby 中:

f = File.open('filename.bin', 'rb')  # read a file in binary mode
f = File.open('filename.txt', 'r')   # read a file in text mode

在 Python 中:

f = open("filename.bin", "rb")  # read a file in binary mode
f = open("filename.txt", "r")   # read a file in text mode

在其他操作系统上,文件系统中的文本文件和二进制文件似乎没有区别。

实际上,我认为文本文件和二进制文件实际上没有区别,因为它们都只是字节的集合。文本文件可能很容易在编辑器中表示,具体取决于编码,而二进制文件通常不能,但底层表示是相同的:按给定顺序排列的字节序列。

为什么 Windows 要做出这种看似不必要的区分?

答案1

Why is there a difference between text and binary files in Windows?

简短回答

没有。

长答案

实际上,我认为文本文件和二进制文件实际上没有区别,因为它们都只是字节的集合。文本文件可能很容易在编辑器中表示出来,具体取决于编码,而二进制文件通常不能,但底层表示是相同的:按给定顺序排列的字节序列。

正如你所说,文件只是一堆字节。就是这样。其内容只有在被解释时才有意义程序。完全有可能一个程序以一种方式解释文件中的字节,而另一个程序以另一种方式解释它们。当您在文本编辑器中打开“二进制”文件时,它会将字节解释为文本并显示它们。如果文件不是“纯文本”,那么结果可能是乱码,但程序仍在执行解释和输出它们的工作。

在许多不同的编程语言中,都有专门的构造来解决 Windows 区分文本和二进制文件这一事实。

Windows 则不然。实际情况是,大多数此类编程语言都是在其他操作系统(如 Unix、Linux 等)上发展起来的,因此对原生纯文本文件使用不同的行尾。它们可能还使用不同的编码,但通常行尾会因平台而异。

以下是常见平台和行尾的列表:

  • Unix、Linux - 换行
  • Windows - 回车、换行
  • Mac(历史上)- 回车
  • (一些旧的操作系统(例如,Acorn BBC)- 换行、回车)

为什么 Windows 要做出这种看似不必要的区分?

Windows 是一个操作系统,它本身不区分任何东西。你应该问的问题是哪一个部分Windows 的命令提示符是不同的。在这种情况下,命令提示符对文本和二进制文件的处理方式不同,即使如此,它也取决于所使用的命令。例如,命令del foobar.txt与没有什么不同del foobar.bin,但是copy a.txt + b.txt c.txt与为什么不同copy /b a.bin + b.bin c.bin?因为 Windows 命令提示符想要提供帮助,并将文本文件解释为文本文件,并复制线输出(在文件之间添加换行符),但复制二进制文件照原样不受干扰。

例如,在 Ruby 中:
f = File.open('filename.bin', 'rb') # read a file in binary mode
f = File.open('filename.txt', 'r') # read a file in text mode
在 Python 中:
f = open("filename.bin", "rb") # read a file in binary mode
f = open("filename.txt", "r") # read a file in text mode
在其他操作系统上,文件系统似乎没有文本文件和二进制文件之间的区别。

这些都是脚本语言,因此可以从命令行运行。处理文本输入文件时,通常不会出现太多问题,但对于二进制文件,您可以使用二进制模式来避免命令提示符预处理文件并将其作为原始字节传递。

在 Linux 中,当您键入或传输文件时,shell 会传递所有原始字节,而不是像 Windows 命令提示符那样将其预处理为文本。

也就是说,根据程序以及输入文件的传递方式,它可以轻松地完全避免预处理。例如,C:\>pyhton foobar.py baz.bin将传递姓名输入文件的脚本,然后按需要打开它,而C:\>type baz.bin | python foobar.py命令提示符会读取文件,然后传递每行对于脚本来说,这对于二进制文件来说是没有用的。

不同的模式仅仅允许灵活性并允许您安全地操作并按照您期望的方式处理文件。

答案2

CP/M(微型计算机控制程序)由 Digital Research 于 20 世纪 70 年代创建。CP/M 中的文件大小以 128 字节磁盘扇区数表示 - 换句话说,无法获得文件大小的确切字节数。这对于二进制文件来说不是什么大问题,因为额外的 127 字节 NULL(或其他)通常不会对程序加载产生负面影响。然而,对于文本文件来说,这是一个问题,因为文本文件的长度可以是任意的。

因此,CP/M 区分了二进制文件和文本文件。按照惯例,文本文件的最后一个字节是带内 Control-Z 字符 - 您读取文件直到看到 ^Z,然后停止。(二进制文件不需要此处理;您只需加载原始扇区数。)

CP/M 非常流行,许多人都对其进行了攻击。攻击它的人之一名叫 Tim Paterson,他供职于一家名为 Seattle Computer Products 的小公司。他为 x86 级硬件制作了一款名为 QDOS(Quick and Dirty Operating System,快速而肮脏的操作系统)的 CP/M 克隆版,它模仿了 CP/M 的相当一部分功能设计。后来,QDOS 被一个名叫比尔·盖茨的辍学者买下,他对其进行了进一步的改进,盲目地继承了其所有设计缺陷和局限性,并创建了 MS-DOS。而 Windows 本身就是在 MS-DOS 之上的临时拼凑版。

尽管微软后来学会了——可能纯属偶然——如何创建一个能够维护文件精确字节数的文件系统,但文本和二进制文件之间的区别仍然存在,即使它不再具有任何有用的用途。

答案3

你知道 Python 也可以在 *nix 和 mac 上运行,对吧?并且这些操作系统上的函数也一样?这不仅仅是 Windows 的问题。查看维基百科关于二进制文件的文章 - 第一行总结得很好:

二进制文件是一种非文本文件的计算机文件;它可能包含任何类型的数据,以二进制形式编码以供计算机存储和处理。

它继续指出:

二进制文件通常被认为是字节序列,这意味着二进制数字(位)以八为一组。二进制文件通常包含旨在解释为文本字符以外的其他内容的字节。

而文本文件则简单得多:

文本文件...是一种计算机文件,其结构为一系列电子文本行。文本文件存在于计算机文件系统中。文本文件的结尾通常通过在文本文件的最后一行后放置一个或多个特殊字符(称为文件结尾标记)来表示

所以是的,答案是它们都是字节序列,但它们编码数据的方法非常不同。文本编辑器被编程为读取文本文件的编码,二进制读取器被编程为读取二进制文件的编码。当您在 python 或 ruby​​ 中调用这些函数时,您正在告诉它期望从文件中获取什么编码,以便它正确地对其进行解码。无论您使用哪种操作系统,这都是相同的。

相关内容