我想这里的每个人都熟悉这句谚语,即所有文本文件都应该以换行符结尾。我已经知道这个“规则”很多年了,但我一直在想——为什么?


当前回答

每一行都应该以换行符结尾,包括最后一行。有些程序在处理文件的最后一行时遇到问题,如果它不是换行符。

GCC对此发出警告,并不是因为它无法处理文件,而是因为它必须作为标准的一部分。

C语言标准说非空的源文件应以换行符结尾,换行符前不得紧跟反斜杠字符。由于这是一个“应”条款,我们必须发出一条违反此规则的诊断信息。这在ANSI C 1989标准第2.1.1.2节中。ISO C 1999标准(可能还有ISO C 1990标准)第5.1.1.2节。

参考:GCC/GNU邮件存档。

其他回答

除了上述实际原因之外,如果Unix的创始人(Thompson、Ritchie等人)或他们的Multics前辈意识到使用行终结符而不是行分隔符是有理论原因的,我也不会感到惊讶:使用行终结器,您可以对所有可能的行文件进行编码。使用行分隔符,零行文件和包含单个空行的文件之间没有区别;它们都被编码为包含零字符的文件。

因此,原因如下:

因为POSIX就是这样定义它的。因为有些工具期望它或没有它的“错误行为”。例如,wc-l不会计算最后的“行”,如果它不以换行结尾。因为它简单方便。在Unix上,cat只起作用,而且没有任何复杂的问题。它只复制每个文件的字节,不需要任何解释。我不认为DOS等同于猫。使用副本a+b c将最终将文件a的最后一行与文件b的第一行合并。因为零行的文件(或流)可以与一个空行的文件区分开来。

一个单独的用例:当文本文件受版本控制时,提交卫生。

如果将内容添加到文件末尾,则先前是最后一行的行将被编辑为包含换行符。这意味着,打开文件以了解该行最后一次编辑的时间将显示换行符添加,而不是您实际希望看到的提交。

(该示例特定于git,但同样的方法也适用于其他版本控制系统。)

假设文件正在被处理,而文件仍由另一个进程生成。

可能与此有关?指示文件已准备好处理的标志。

为什么文本文件应该以换行符结尾?

因为这是最明智的选择。

获取包含以下内容的文件:,

one\n
two\n
three

其中,\n表示换行符,在Windows上是返回字符,\r\n后跟换行符,因为它很酷,对吗?

这个文件有多少行?Windows说3,我们说3,POSIX(Linux)说文件是残缺的,因为文件末尾应该有一个。

无论如何,你会说它的最后一行是什么?我想任何人都同意三行是文件的最后一行,但POSIX表示这是一个残缺的行。

第二行是什么?哦,这里有第一个强烈的分离:

Windows说两个是因为文件是“用换行符分隔的行”(wth?);POSIX说2,并补充说这是一条真实、诚实的路线。

那么,选择Windows的后果是什么?简单:

你不能说文件是由行组成的

为什么?尝试从上一个文件中取出最后一行并复制几次。。。你得到了什么?这:

one\n
two\n
threethreethreethree

相反,尝试交换第二行和第三行。。。你会发现:

one\n
threetwo\n

因此

您必须说,文本文件是行和\n的交替,以行开始,以行结束

这真是一口,对吧?

你想要另一个奇怪的结果?

你必须接受一个空文件(0字节,实际上是0位)是一个单行文件,神奇的是,因为它们在微软很酷

这真是太疯狂了,你不觉得吗?

POSIX选择的后果是什么?

顶部的文件有点残缺,我们需要一些黑客来处理它。

是认真的

在前面的文本中,我是挑衅性的,因为处理缺少结尾的文本文件会迫使您使用特殊的滴答声/黑客来处理它们。你总是需要一个if/else来让事情运转起来,其中处理残缺行的分支只处理残缺行,所有其他行都采用另一个分支。这有点种族主义,不是吗?

我的结论

我赞成POSIX对行的定义,原因如下:

文件自然被认为是一系列行一行不应该是这样或那样的,这取决于它在文件中的位置空文件不是单行文件,拜托!您不应该被迫对代码进行黑客攻击


是的,Windows确实鼓励您省略后面的\r\n。如果需要下面的两行文件,则必须省略尾部,否则文本编辑器会将其显示为三行文件:

这源于使用简单终端的早期。换行符用于触发传输数据的“刷新”。

今天,不再需要换行符。当然,如果没有换行符,许多应用程序仍然存在问题,但我认为这是这些应用程序中的一个错误。

然而,如果你有一个需要换行符的文本文件格式,那么你可以得到非常便宜的简单数据验证:如果文件以结尾没有换行符的行结尾,那么你就知道文件已损坏。每行只有一个额外的字节,您可以高精度地检测损坏的文件,几乎不需要CPU时间。