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

Posted

技术标签:

【中文标题】为啥文本文件应该以换行符结尾?【英文标题】:Why should text files end with a newline?为什么文本文件应该以换行符结尾? 【发布时间】:2010-10-18 07:10:37 【问题描述】:

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

【问题讨论】:

只是挑剔。它不是文件末尾的“新行”。这是最后一行末尾的“换行符”。另外,请参阅相关问题的最佳答案:***.com/questions/16222530/… 再吹毛求疵,他实际上并没有写“换行”,他写了“换行”,这是正确的。 不熟悉,但想知道我确实是因为多余的换行符实际上破坏了事情的情况对我来说有点太高了 我目前正在使用 Node.js 流来逐行解析纯文本数据,并且缺少终端换行符很烦人,因为我必须为何时添加额外的逻辑流的输入端已完成/关闭,以确保处理最后一行。 way Unix regards 在文件末尾的一般行为如下: \n 字符不开始行;相反,他们结束了他们。因此, \n 是行终止符,而不是行分隔符。第一行(像所有行一样)不需要 \n 来启动它。最后一行(像所有行一样)需要一个 \n 来结束它。文件末尾的 \n 不会创建额外的行。但是,有时文本编辑器会在此处添加可见的空白行。甚至 emacs 也这样做,optionally. 【参考方案1】:

因为那是how the POSIX standard defines a line

3.206 线 零个或多个非 字符加上一个终止 字符的序列。

因此,不以换行符结尾的行不被视为实际行。这就是为什么某些程序在处理文件的最后一行时遇到问题的原因,如果它不是换行符终止的话。

在终端仿真器上工作时,该指南至少有一个硬性优势:所有 Unix 工具都期望这个约定并使用它。例如,当使用cat 连接文件时,以换行符终止的文件与没有的文件具有不同的效果:

$ more a.txt
foo
$ more b.txt
bar$ more c.txt
baz
$ cat a,b,c.txt
foo
barbaz

而且,正如前面的示例还演示的那样,当在命令行上显示文件时(例如通过more),换行符终止的文件会导致正确显示。未正确终止的文件可能会出现乱码(第二行)。

为了保持一致性,遵循这条规则非常有帮助——否则在处理默认的 Unix 工具时会产生额外的工作。


换个角度想一想:如果行不以换行符结尾,那么让cat 等命令有用就更难了:你如何创建一个命令来连接文件,这样

    它将每个文件的开头放在一个新行上,这在 95% 的情况下都是您想要的;但是 它允许合并两个文件的最后一行和第一行,如上例b.txtc.txt之间的?

当然这是可解决的,但是您需要使cat 的使用更加复杂(通过添加位置命令行参数,例如cat a.txt --no-newline b.txt c.txt),现在是命令 而不是每个单独的文件控制它与其他文件的粘贴方式。这几乎肯定不方便。

... 或者您需要引入一个特殊的标记字符来标记应该继续而不是终止的行。好吧,现在您遇到了与 POSIX 相同的情况,除了反转(行继续而不是行终止字符)。


现在,在非 POSIX 兼容 系统(现在主要是 Windows)上,重点是没有实际意义的:文件通常不以换行符结尾,并且(非正式)定义例如,行可能是“由换行符分隔的文本”(注意重点)。这是完全有效的。然而,对于结构化数据(例如编程代码),它使解析变得更加复杂:这通常意味着必须重写解析器。如果解析器最初是根据 POSIX 定义编写的,那么修改令牌流可能比修改解析器更容易——换句话说,在输入的末尾添加一个“人工换行符”令牌。

【讨论】:

虽然现在纠正起来非常不切实际,但显然 POSIX 在定义该行时犯了一个错误——作为与此问题相关的问题数量的证据。一行应该被定义为零个或多个以 结尾的字符。解析器复杂性不是一个有效的问题。复杂性应尽可能从程序员的头脑中转移到库中。 @DougCoburn 这个答案曾经有一个详尽的技术讨论,解释了为什么这是错误的,以及为什么 POSIX 做了正确的事情。不幸的是,这些 cmets 显然最近被一位过分热心的版主删除了。简而言之,这与解析复杂性无关;相反,您的定义使得以既有用又一致的方式编写诸如 cat 之类的工具变得更加困难。 @Leon POSIX 规则是关于减少边缘情况的。它做得非常漂亮。我实际上有点不知所措,为什么人们无法理解这一点:这是对线的最简单、自洽的定义。 @BT 我认为您假设我的示例 更方便的工作流程是做出决定的原因。这不是,这只是一个结果。 原因 是 POSIX 规则是最简单的规则,它使解析器中的行处理变得最简单。我们甚至进行辩论的唯一原因是 Windows 的做法不同,因此,有许多工具在 POSIX 文件上失败。如果每个人都做 POSIX,就不会有任何问题。然而,人们抱怨的是 POSIX,而不是 Windows。 @BT 我只是指 Windows 来指出 POSIX 规则没有意义的情况(换句话说,我在向你扔骨头)。我很高兴不再在这次讨论中提及它。但是,您的主张就更没有意义了:在 POSIX 平台上,讨论具有不同行尾约定的文本文件根本没有意义,因为没有理由生成它们。有什么好处?字面上没有。 — 总而言之,我真的不明白这个答案(或 POSIX 规则)正在引起的仇恨。坦率地说,这完全不合理。【参考方案2】:

每一行都应该以换行符结束,包括最后一行。如果文件不是换行符终止,则某些程序在处理文件的最后一行时会出现问题。

GCC 警告它不是因为它不能处理文件,而是因为它必须作为标准的一部分。

C 语言标准说 非空源文件应以换行符结尾,换行符前面不应紧跟反斜杠。

由于这是一个“shall”子句,我们必须发出一条违反此规则的诊断消息。

这在 ANSI C 1989 标准的第 2.1.1.2 节中。 ISO C 1999 标准(也可能是 ISO C 1990 标准)的第 5.1.1.2 节。

参考:The GCC/GNU mail archive。

【讨论】:

请编写好的程序,然后允许在处理时在需要的地方插入换行符,或者能够正确处理“缺失”的行......事实上,这些不是缺失的 @BilltheLizard,“如果文件的最后一行不是换行符终止,某些程序在处理文件的最后一行时会出现问题”有哪些示例? @Pacerier wc -l 不会计算文件的最后一行,如果它不是换行符终止的话。此外,cat 会将文件的最后一行与下一个文件的第一行合并为一个,如果第一个文件的最后一行不是换行符终止。几乎所有寻找换行符作为分隔符的程序都有可能搞砸。 @BilltheLizard,我的意思是wc 有already been mentioned.... @BilltheLizard,我的错,澄清一下:如果不是换行符终止,哪些程序在处理文件的最后一行时遇到问题(除了那些已经被大量提及的程序)在catwc 之类的线程上?【参考方案3】:

此答案是对技术答案而非意见的尝试。

如果我们想成为 POSIX 纯粹主义者,我们将一行定义为:

零个或多个非 字符加上一个终止 字符的序列。

来源:https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206

不完整的行为:

文件末尾的一个或多个非 字符序列。

来源:https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_195

文本文件为:

包含组织成零行或多行的字符的文件。这些行不包含 NUL 字符,长度不能超过 LINE_MAX 个字节,包括 字符。尽管 POSIX.1-2008 不区分文本文件和二进制文件(参见 ISO C 标准),但许多实用程序仅在对文本文件进行操作时产生可预测或有意义的输出。具有此类限制的标准实用程序始终在其 STDIN 或 INPUT FILES 部分中指定“文本文件”。

来源:https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_397

一个字符串为:

由第一个空字节终止并包括第一个空字节的连续字节序列。

来源:https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_396

因此,我们可以得出,我们可能遇到任何类型问题的唯一时间是我们处理文件的的概念或文本文件的文件(即文本文件是零行或多行的组织,我们知道一行必须以结束)。

恰当的例子:wc -l filename

我们从wc的手册中读到:

行定义为由 字符分隔的字符串。

如果它们是 text 文件,那么对 javascript、HTML 和 CSS 文件有何影响?

在浏览器、现代 IDE 和其他前端应用程序中,在 EOF 跳过 EOL 没有问题。应用程序将正确解析文件。它必须因为并非所有操作系统都符合 POSIX 标准,因此非操作系统工具(例如浏览器)根据 POSIX 标准(或任何操作系统级标准)处理文件是不切实际的。

因此,我们可以相对确信 EOF 的 EOL 对应用程序级别几乎没有负面影响 - 无论它是否在 UNIX 操作系统上运行。

此时我们可以自信地说,在客户端处理 JS、HTML、CSS 时,在 EOF 处跳过 EOL 是安全的。实际上,我们可以说缩小这些文件中的任何一个,不包含 是安全的。

我们可以更进一步说,就 NodeJS 而言,它也不能遵守 POSIX 标准,因为它可以在不符合 POSIX 的环境中运行。

那我们还剩下什么?系统级工具。

这意味着可能出现的唯一问题是工具努力使其功能符合 POSIX 语义(例如,wc 中所示的行定义)。

即便如此,并不是所有的 shell 都会自动遵守 POSIX。例如,Bash 不默认为 POSIX 行为。有一个开关可以启用它:POSIXLY_CORRECT

关于 EOL 的价值是 值得深思:https://www.rfc-editor.org/old/EOLstory.txt

为了所有实际意图和目的,留在工具轨道上,让我们考虑一下:

让我们使用没有 EOL 的文件。在撰写本文时,此示例中的文件是没有 EOL 的缩小 JavaScript。

curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o x.js
curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o y.js

$ cat x.js y.js > z.js

-rw-r--r--  1 milanadamovsky   7905 Aug 14 23:17 x.js
-rw-r--r--  1 milanadamovsky   7905 Aug 14 23:17 y.js
-rw-r--r--  1 milanadamovsky  15810 Aug 14 23:18 z.js

请注意,cat 文件大小恰好是其各个部分的总和。如果 JavaScript 文件的连接是 JS 文件的关注点,那么更合适的关注点是每个 JavaScript 文件都以分号开头。

正如该线程中的其他人所提到的:如果你想cat 两个文件的输出变成一行而不是两行怎么办?换句话说,cat 做了它应该做的事情。

catman 只提到读取输入到 EOF,而不是 。请注意,cat-n 开关也将打印出非 终止行(或 incomplete line)作为 line - 这是计数从 1 开始(根据man。)

-n 为输出行编号,从 1 开始。

现在我们了解了 POSIX 如何定义 line ,这种行为变得模棱两可,或者说真的不合规。

了解给定工具的用途和合规性将有助于确定以 EOL 结束文件的重要性。在 C、C++、Java (JAR) 等中...一些标准将规定换行符以表示有效性 - JS、HTML、CSS 不存在这样的标准。

例如,可以使用 awk 'x++END print x' filename 代替 wc -l filename ,并且请放心,任务的成功不会受到我们可能想要处理但我们没有编写的文件的危害(例如第三方库,例如缩小的 JS 我们curld) - 除非我们的意图是真正按照 POSIX 兼容的方式计算

结论

在现实生活中,对于某些文本文件(如 JS、HTML 和 CSS)跳过 EOL 会产生负面影响(如果有的话)的情况很少。如果我们依赖 的存在,我们将工具的可靠性限制在我们创作的文件中,并让我们自己面对第三方文件引入的潜在错误。

故事的寓意:工程师工具没有在 EOF 依赖 EOL 的弱点。

请随意发布适用于 JS、HTML 和 CSS 的用例,我们可以在其中检查跳过 EOL 的不利影响。

【讨论】:

POSIX 未在问题中标记...关于 MVS/OS 行尾?还是 MS-DOS 行尾?顺便说一句,所有已知的 posix 系统都允许没有最后一行结尾的文本文件(没有发现符合 posix 的声明系统,其中“文本文件”在内核中具有特殊处理以插入适当的换行符以防万一它没有它) “在现实生活中很少有跳过的用例......”不正确。 在现实生活中,我每天都审查代码,处理由于文件缺少尾随 newline 而导致的无用合并差异是浪费时间。为了保持一致性,每一行(甚至是文件中的最后一行)都应该正确终止。【参考方案4】:

可能与difference between有关:

文本文件(每行应该以换行符结束) 二进制文件(没有真正的“行”可言,必须保留文件的长度)

如果每一行都以行尾结尾,例如,这样可以避免连接两个文本文件会使第一个运行的最后一行变成第二个运行的第一行。

另外,编辑器可以在加载时检查文件是否以行尾结尾,将其保存在本地选项“eol”中,并在写入文件时使用。

几年前(2005 年),许多编辑(ZDE、Eclipse、Scite...)确实“忘记”了最后的 EOL,which was not very appreciated。 不仅如此,他们还错误地将最终 EOL 解释为“开始新行”,实际上开始显示另一行,就好像它已经存在一样。 与在上述编辑器之一中打开它相比,使用具有良好行为的文本编辑器(如 vim)的“正确”文本文件非常明显。它在文件的实际最后一行下方显示了一个额外的行。你会看到这样的东西:

1 first line
2 middle line
3 last line
4

【讨论】:

+1。我在遇到这个问题时发现了这个 SO question。在 Eclipse 中显示这个“假”的最后一行是 非常 烦人的,如果我删除它,那么 git(以及所有其他期望 EOL 的 unix 工具)会抱怨。另外,请注意,这不仅发生在 2005 年:Eclipse 4.2 Juno 仍然存在这个问题。 @MestreLion,继续***.com/questions/729692/…【参考方案5】:

一些工具期望这一点。例如,wc 期望这样:

$ echo -n "Line not ending in a new line" | wc -l
0
$ echo "Line ending with a new line" | wc -l
1

【讨论】:

我不会说“一些”,我会说 大多数 工具期望文本文件(如果不是全部的话)。 cat, git, diff, wc, grep, sed...这个列表很大 也许有人会说wc 没有期望这一点,因为它只是在 POSIX 定义的“线”中工作,而不是大多数人的对“线”的直观理解。 @Guildenstern 直观的定义是wc -l 在这两种情况下都打印1,但有些人可能会说第二种情况应该打印2 @Flimm 如果您将\n 视为行终止符,而不是像 POSIX/UNIX 那样作为行分隔符,那么期望第二种情况打印 2 绝对是疯狂的。【参考方案6】:

一个单独的用例:当您的文本文件受版本控制时(在这种情况下,特别是在 git 下,尽管它也适用于其他文件)。如果内容被添加到文件的末尾,那么之前是最后一行的行将被编辑为包含换行符。这意味着blameing 文件以找出该行最后一次编辑的时间将显示文本添加,而不是您真正想看到的之前的提交。

【讨论】:

diff 和 blame 应该只更新以检测“新行”而不是“新行”(\n)。问题解决了。 您可以使用 -w 标签忽略空格更改,但它们不是默认设置。 这是我开始在文件末尾添加换行符的主要原因【参考方案7】:

基本上有很多程序如果没有得到最终的 EOL EOF,就无法正确处理文件。

GCC 会就此向您发出警告,因为它是 C 标准的一部分。 (显然是第 5.1.1.2 节)

"No newline at end of file" compiler warning

【讨论】:

GCC 不是不能处理文件,它必须作为 C 标准的一部分给出警告。 IIRC,MSVC 2005 抱怨 C 文件以不完整的行结尾并且可能拒绝编译它们。【参考方案8】:

我自己多年来一直想知道这一点。但我今天遇到了一个很好的理由。

想象一个每行都有一条记录的文件(例如:CSV 文件)。并且计算机正在文件末尾写入记录。但它突然崩溃了。哎呀,最后一行完成了吗? (不是很好的情况)

但是如果我们总是终止最后一行,那么我们就会知道(只需检查最后一行是否终止)。否则,为了安全起见,我们可能每次都必须丢弃最后一行。

【讨论】:

我同意,我一直认为这是一个穷人的“校验和”,它说当缺少行尾时,它表明文件可能被截断。当然,反过来也不能保证。至少对于文本文件;对于二进制文件,我不知道它是否是一个有效的约定。 @alfC 这是一个很好的描述。这就是我使用它的方式。是的,这当然不适用于二进制文件【参考方案9】:

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

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

但是,如果您有一个文本文件格式,其中 需要 换行符,您可以非常便宜地获得简单的数据验证:如果文件以末尾没有换行符的行结束,您知道文件损坏。每行只需一个额外的字节,您就可以高精度检测损坏的文件,并且几乎不需要 CPU 时间。

【讨论】:

现在对于 text 文件在 EOF 处换行可能不是必需的,但它是一个有用的 convention,它可以使大多数 unix 工具与一致的结果。这根本不是错误。 我们很多人根本不使用 Unix 工具,我们不在乎。 不只是 unix 工具,任何工具如果可以采用合理的文件格式,都会更好地工作和/或编码更简单。 @Sam Watkins 同意简单且定义良好的 格式 很好。然而代码仍然需要验证,而不是假设 data 是格式兼容的。 @MestreLion 这是一组符合愚蠢标准的糟糕工具的无用遗产。 extremist programming 的这些人工制品(即一切文件!一切都应该是纯文本!)在他们发明后并没有很快消失,因为它们是历史特定时刻唯一可用的此类工具。 C 被 C++ 取代,它不是 POSIX 的一部分,它在 EOF 时不需要 EOL,并且(显然)不鼓励 *nix luddists 的使用。【参考方案10】:

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

所以,原因是:

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

【讨论】:

【参考方案11】:

还有一个实际的编程问题,文件末尾缺少换行符:read Bash 内置(我不知道其他 read 实现)无法按预期工作:

printf $'foo\nbar' | while read line
do
    echo $line
done

只打印foo!原因是当read 遇到最后一行时,它会将内容写入$line 但返回退出代码1,因为它到达了EOF。这打破了while 循环,因此我们永远无法到达echo $line 部分。如果您想处理这种情况,您必须执行以下操作:

while read line || [ -n "$line-" ]
do
    echo $line
done < <(printf $'foo\nbar')

也就是说,如果 read 由于文件末尾的非空行而失败,则执行 echo。当然,在这种情况下,输出中会多出一个输入中没有的换行符。

【讨论】:

【参考方案12】:

大概只是一些解析代码期望它在那里。

我不确定我是否会将其视为“规则”,而且我肯定不会严格遵守。大多数明智的代码都知道如何逐行解析文本(包括编码)(任何行尾选择),最后一行有或没有换行符。

确实 - 如果您以新行结尾:(理论上)EOL 和 EOF 之间是否有空的最后一行?一个值得思考的...

【讨论】:

这不是规则,而是约定:line 是以end-of-line 结尾的东西。所以不,EOL 和 EOF 之间没有“空的最后一行”。 @MestreLion:但是有问题的字符没有被命名为“行尾”,它被命名为“换行符”和/或“换行符”。行分隔符,而不是行终止符。结果是最后一个空行。 没有(正常)工具会将文件的最后 EOL(CR、LF 等)计为额外的空行。如果没有结束 EOL,所有 POSIX 工具都不会将文件的最后一个字符计为一行。无论 EOL 字符 name 是“换行符”还是“回车符”(没有名为“换行符”的字符),出于所有实际目的,明智的工具都将其视为行 终止符 i>,不作为行分隔符 @MestreLion,你确定“线路终结者”是理智的吗?找几个非程序员做一个快速调查。您会很快意识到 lines 的概念更接近于“行分隔符”的概念。 “行终结符”的概念is just weird. @Sahuagin:这不是 my 观点,这是 POSIX 标准定义行的方式。一个 0 字节的空文件有 0 行,因此没有 EOL,而一个文件被认为只有一个空行,它确实需要 EOL。另请注意,这仅在您想 count 文件中的行时才相关,因为显然任何编辑器都会让您“获取”到下一行(或第一行),无论是否已经存在 EOL在那里。【参考方案13】:

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

正如许多人所说,因为:

    许多程序运行不佳,或者没有它就失败。

    即使可以很好地处理文件的程序也缺少结尾 '\n',该工具的功能可能无法满足用户的期望 - 在这种极端情况下可能不清楚。

    程序很少不允许最终'\n'(我不知道)。


这引出了下一个问题:

对于没有换行符的文本文件,代码应该如何处理?

    最重要 - 不要编写假定文本文件以换行符结尾的代码假设文件符合某种格式会导致数据损坏、黑客攻击和崩溃。示例:

    // Bad code
    while (fgets(buf, sizeof buf, instream)) 
      // What happens if there is no \n, buf[] is truncated leading to who knows what
      buf[strlen(buf) - 1] = '\0';  // attempt to rid trailing \n
      ...
    
    

    如果需要最后的尾随 '\n',请提醒用户它不存在以及所采取的操作。 IOW,验证文件的格式。注意:这可能包括对最大行长、字符编码等的限制。

    明确定义、记录、代码对缺少的最终 '\n' 的处理。

    尽量不要生成缺少结尾'\n'的文件。

【讨论】:

【参考方案14】:

这里已经很晚了,但我刚刚遇到了文件处理中的一个错误,这是因为文件没有以空换行符结尾。我们正在处理带有sed 的文本文件,sed 省略了输出中的最后一行,这导致了无效的 json 结构并将进程的其余部分发送到失败状态。

我们所做的只是:

有一个示例文件说:foo.txt,其中包含一些json 内容。

[
    someProp: value
,

    someProp: value
] <-- No newline here

该文件是在寡妇机器中创建的,并且窗口脚本正在使用 PowerShell 命令处理该文件。都很好。

当我们使用sed 命令sed 's|value|newValue|g' foo.txt &gt; foo.txt.tmp 处理同一个文件时

新生成的文件是

[
    someProp: value
,

    someProp: value

然后,由于 JSON 无效,其余进程失败了。

因此,以空的新行结束文件始终是一个好习惯。

【讨论】:

echo -n foo | sed ''sed (GNU sed) 4.4 配合良好 以空的新行结束文件?什么是空新行【参考方案15】:

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

因为这是最明智的选择。

取一个内容如下的文件,

one\n
two\n
three

其中\n 表示换行符,在Windows 上是\r\n,后面是换行符,因为它很酷,对吧?

这个文件有多少行? Windows 说 3,我们说 3,POSIX (Linux) 说文件已损坏,因为文件末尾应该有一个 \n

不管怎样,你会说它的最后一行是什么?我想有人同意three 是文件的最后一行,但 POSIX 说这是一条残缺的行。

第二行是什么?哦,这里我们有第一个强大的separation:

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

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

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

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

one\n
two\n
threethreethreethree

尝试交换第二行和第三行...你会得到这个:

one\n
threetwo\n

因此

你必须说一个文本文件是行和\ns的交替,它以一行开始,以一行结束

这真是一口,对吧?

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

您必须接受空文件(0 位)是单行文件,这很神奇,总是因为它们在微软很酷

这很疯狂,你不觉得吗?

POSIX 选择的后果是什么?

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

认真

在前面的文字中,我是在挑衅,因为处理末尾缺少\n 的文本文件会迫使您用ad-hoc 滴答/黑客来对待它们。你总是需要一个if/else 来让事情正常工作,处理残废线路的分支只处理残废线路,所有其他线路都使用另一个分支。这有点种族主义,不是吗?

我的结论

我赞成使用 POSIX 定义一行,原因如下:

文件自然地被认为是一系列行 一行不应该是一回事,具体取决于它在文件中的位置 空文件不是单行文件,加油! 不应强迫您对代码进行修改

【讨论】:

你的回答让我不同意posix的选择。它不必要地引入了无效的文件状态,并且使“换行符”的含义不正确。 “换行符”应该被称为“换行符”,它是唯一将文本内容变成行的东西,没有它,内容(出于某种原因)毫无意义。 @DaveCousineau,对不起,我不明白。为什么 line marker 是更好的选择?这是一个准确的名字吗?例如,它的名称中的什么暗示它应该是行的尾随字符? 行终止符 可能是更好的选择。但无论如何,尝试将 换行符 替换为 \n,您会看到您的评论发生了怎样的变化:它使 \n 的含义不正确。 \n 应改为“线标记”。我会随你的便接电话,即使是毒贩,还是一样的。 是什么让换行符、换行符、换行符、nuova riga, a capo 或任何你想称呼它的东西,不是它的名字,而是它在 POSIX 定义中的作用文件是。 “换行”的含义是它换行,显然它没有。相反,它将当前的非线变成了线。 “行终止符”确实有效。但我仍然认为我不同意有不必要的无效状态。 “text\ntext”没有理由不应该是可破译的文本。 我不确定这是否重要,但如果我们说“行”必须至少有一个字符(即空字符串不是一行)。也许我错过了一些东西。 (我的 cmets 的背景是,我最近强迫自己开始在我的文本文件的末尾添加一个“行终止符”,尽管我对此事有直觉。我还没有决定,但阅读你的答案让我不想添加它们。)【参考方案16】:

我一直认为这条规则来自于解析没有结尾换行符的文件很困难的日子。也就是说,您最终将编写代码,其中行尾由 EOL 字符或 EOF 定义。假设一行以 EOL 结尾更简单。

但我相信该规则源自需要换行符的 C 编译器。正如“No newline at end of file” compiler warning 所指出的,#include 不会添加换行符。

【讨论】:

【参考方案17】:

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

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

【讨论】:

【参考方案18】:

我个人喜欢源代码文件末尾的新行。

它可能起源于 Linux 或所有 UNIX 系统。我记得有编译错误(如果我没记错的话是 gcc),因为源代码文件没有以空的新行结尾。为什么它是这样制作的,值得怀疑。

【讨论】:

【参考方案19】:

恕我直言,这是个人风格和观点的问题。

在过去,我没有换行。保存一个字符意味着通过 14.4K 调制解调器的速度更快。

稍后,我添加了换行符,以便使用 shift+downarrow 更容易选择最后一行。

【讨论】:

以上是关于为啥文本文件应该以换行符结尾?的主要内容,如果未能解决你的问题,请参考以下文章

C Primer Plus

实用小命令

我应该使用哪个函数将非结构化文本文件读入 R? [关闭]

模糊寻找文本行子程序,返回以换行符分隔的文本

Java中为啥在字符串中加入了\n还是不能换行,且在eclipse中显示的是换行,找到绝打开文本

如何让Hadoop读取以gz结尾的文本格式的文件