'\ n'和'\ r \ n'之间的区别


99

是的,我知道可以'\n'在UNIX 中写换行符,而对于Windows,则有两个字符序列:'\r\n'。从理论上讲,所有这些都很好,但是我的问题是为什么?为什么在Windows中回车符是多余的?如果UNIX可以做到这一点,\n为什么Windows则需要两个字符来完成呢?

我正在阅读David Beazley的Python书,他说:

例如,在Windows上,写入字符'\ n'实际上会输出两个字符的序列'\ r \ n'(并且在读回文件时,'\ r \ n'被转换回单个'\ n'字符)。

为什么要付出额外的努力?

我会说实话。我很早就知道它们之间的区别了,但是从来没有问过为什么。我希望今天能回答。

谢谢你的时间。


5
还应该注意Windows并不是唯一使用的Windows \r\n。大多数基于文本的Internet协议(例如SMTP,HTTP等)也使用它,其原因与Windows(即历史记录)大致相同。
迪恩·哈丁

3
另外,在Java中并使用格式字符串(例如System.out.printf()String.format())时,请确保%n出于操作系统兼容的目的将其用作CRLF。\n不推荐使用。
加里·罗

我看过\n\r几次了。(我认为这是NetWare提供的东西。)
grawity 2010年


1
很少有Windows程序实际需要CRLF。CRLF可能是默认值,但是几乎所有内容都会自动检测并使用LF即可。我在Windows上将所有文本编辑器配置为对所有新文件都使用LF,这实际上不是问题。
凯文

Answers:


124

向后兼容。

Windows与MS-DOS向后兼容(因此,即使如此也是如此),并且MS-DOS使用CR-LF约定,因为MS-DOS与使用CR-LF约定的CP / M-80(有点偶然)兼容。是您驾驶打印机的方式(因为打印机最初是计算机控制的打字机)。

打印机有一个单独的命令可将纸张向上移动一行到新行,还有一个单独的命令可将笔架(安装纸张的位置)返回左边缘。

这就是为什么。而且,是的,这很烦人,但这是一揽子交易的一部分,它使MS-DOS可以战胜CP / M,Windows 95可以战胜DOS之上的所有其他GUI,而Windows XP可以战胜从Windows 98。

(注意:现代激光打印机仍然具有这些命令,因为它们也与早期打印机向后兼容-特别是HP可以做到这一点)

对于那些不熟悉打字机的人,下面的视频展示了打字的方式:http : //www.youtube.com/watch?v=LJvGiU_UyEQ。请注意,即使纸张移动很简单,也要先将其向上移动,然后再将其退回。叮叮通知打字员结束将至,并为此做准备。


3
Unix如何使用\ n仅与那些过去的打印机一起使用?我以为他们确实将Unix控制台连接到打字机类型的打印机?
Senthil Kumaran 2010年

3
@Senthil,在Unix中,换行符由最终驱动程序转换。这只是一个不同的设计决定。

2
准确地说,@ Senthil在Unix中,打印机和终端在操作系统中是抽象的,它们的描述确定了为设备生成哪些字节序列。CP / M没有这样的抽象,而是将其全部留给程序运行-这很可能是因为并非所有程序都需要它,因此在驻留的操作系统中拥有它会从不需要它的程序中夺走宝贵的内存。请记住,CP / M是为16 千字节系统设计的。

1
“因此,可以说是世界上最先进的运输系统的主要设计特征最初是由马鞍的宽度决定的。” 软件也是如此。astrodigital.org/space/stshorse.html
Ryan Michela

1
@Ryan,城市传奇。在snopes.com/history/american/gauge.htm中

20

据我所知,这可以追溯到打字机的时代。

\r 是回车符,即您在页面上键入的位置向左移动(如果这是您的文化,请向右移动)

\n 是新行,它将使您的纸张向上移动一行。

在打字机上仅执行其中的一项操作会把您放在错误的位置,开始写新的一行文本。

当计算机问世时,我猜有些人保留了旧模型,但是其他人意识到这是不必要的,因此将完整的换行符封装为一个字符。


7
那么,为什么Windows 仍然坚持呢?
sukhbir

8
向后兼容。想象一下,如果现在更改文本文档,将会破坏多少个文档
马特·艾伦

4
严格来说,这里的“ oddball”是unixoid“仅使用换行符”,最初(我认为)是为了使存储的字符数减少(在终端驱动程序中转换为CR LF的过程是“ onlcr”标志)控制它用于输出。
Vatine

3
Windows有一个名为DOS的前身,具有相同的行尾。Windows保持兼容性。DOS本身就是CP / M的前身。那也使用CRLF。DOS保持兼容性。CP / M的发展受到DECs TOPS的影响。您可以猜测,他们使用了哪种线尾。:-)兼容性说明了很多。
Mnementh,2010年

5
可以,但是记事本为什么不能识别“ \ n”行尾?
dan04 2011年

8

我不知道这是否是常识,但是应该指出,现代终端仿真器仍然可以理解CR:

$ printf "hey world\rsup\n"
sup world

方便用于进度指示器,例如

for i in {1..100}
do
    printf "\rLoading... %d%%" $i
    sleep 0.01
done
echo

1
在旧的IBM行式打印机(例如1403)上,惯例是将行缓冲区的第一个字符视为回车控制字符。空白表示前进一行并打印。加号表示省略间距,并用于例如下划线。零表示双倍空格,负表示三倍空格。下一页顶部隔开一个“ 1”,其他数字前进到用户定义的垂直位置(用于填写预打印的表格)。
乔治

7

从历史上看,换行意味着压板(您在其上键入的滚轮)旋转了一行,从而导致文本显示在下一行中,但出现在下一列中。

回车的意思是“将您输入的位返回到行首”。

Windows使用CR + LF是因为MS-DOS这样做了,因为CP / M这样做了,因为它对于串行线有意义。

Unix复制了\ n约定,因为Multics这么做了。

我怀疑如果您深入研究,您会发现实施者之间存在政治分歧!

(您省去了额外的乐趣,在Mac约定中(或曾经使用)Mac约定仅使用CR来分隔行。现在Unicode也具有自己的行分隔符U + 2028!)


哇!不知道Mac ...
Michael K 2010年

我不确定您是否会发现政治分歧。您也可能会发现人们独立地做类似的事情。
David Thornley 2010年

1
何时涉及不同的标准机构?我很惊讶没有找到政治原因!
Frank Shearar 2010年

6

换行符的历史(维基百科):

ASCII由ISO和ASA(ANSI的前身组织)同时开发。在1963年至1968年期间,ISO草案标准仅支持将CR + LF或LF用作换行符,而ASA草案仅支持CR + LF。

CR + LF序列在许多采用电传打字机(通常为ASR33)作为控制台设备的早期计算机系统中普遍使用,因为需要此序列将这些打印机放置在新生产线的开头。在这些系统上,通常会常规编写文本以使其与这些打印机兼容,因为尚未很好地开发出将设备的硬件细节隐藏在应用程序中的设备驱动程序的概念。应用程序必须直接与电传打字机对话并遵守其约定。

这两个功能的分离掩盖了以下事实:打印头无法在一个字符的时间内从最右端返回到下一行的开头。这就是为什么总是先将CR与序列一起发送的原因。实际上,通常有必要发送额外的字符(外部CR或NUL,将被忽略)以使打印头有时间移到左边距。

即使电传打字机被具有更高波特率的计算机终端所取代,许多操作系统仍支持自动发送这些填充字符,以与需要多个字符时间才能滚动显示的廉价终端兼容。

MS-DOS(1981)采用了CP / M的CR + LF;CP / M使用CR + LF对于通过串行线使用计算机终端很有意义。此约定由Microsoft的更高版本的Windows操作系统继承。

Multics操作系统于1964年开始开发,仅使用LF作为其换行符。Unix遵循Multics惯例,后来的系统遵循Unix。


在旧的IBM 2741打印机键盘终端上,打印机组件是IBM Selectric弹跳式球形打字机。更改为大写字母会导致球旋转,这需要花费更多时间。在EBCDIC字符代码中,大写字符的位置6为1位。因此,EBCDIC空白(0x40)为大写!如果要打印较长的文档(例如,论文),则可以通过将小写单词之间的空格转换为NUL或小写空格(它们使用不同的字符,如果有记忆,则使用IL)来引入必要的延迟,从而从实质上提高输出速度。 ,返回或跳格时)。
乔治

5

人们问“为什么Unix可以\n而不是Windows 来做什么”呢?这是一个奇怪的问题。

  1. 该操作系统几乎与它无关。应用,库,协议和文件格式如何处理问题更多。除了操作系统读取/写入基于文本的配置或命令行命令的位置以外,对操作系统进行故障都没有意义。
  2. 大多数Windows应用程序都可以读取\n并且都可以\r\n。它们也输出,\r\n使每个人都开心。程序不会简单地“做” \n或做“ 一个”,\r\n而是接受一个,另一个或两个,然后输出一个,另一个或两个。
  3. 作为一名程序员,这几乎绝对不会打扰您。实际上,每种语言/平台都具有编写正确的终端行和最可靠地阅读的功能。我唯一需要解决的问题是当我编写HTTP服务器时 -这是因为某个浏览器(提示:IE之后的第二个最受欢迎的浏览器)在运行\n而不是在使用正确的 浏览器\r\n
  4. 一个更相关的问题是,为什么这么多现代Unix应用程序仅在\n完全了解某些协议和程序不喜欢的情况下才输出?

3
另一个相关的问题:由于许多协议主要是在Unix系统上开发的,因此为什么不使用'\ n'?
David Thornley 2010年

@DavidThornley因为\ r \ n更可能跨平台工作(对于较旧的Mac,\ r \ n对于Windows,对于\ n \ * nix,\ r \ n)。
2015年

4

约定在其各种系统上(在unix类型的系统上为\ n,在Windows上为\ r \ n等)保持不变的原因是,一旦选择了约定,就无法在不破坏大量用户文件的情况下对其进行更改。而这通常被皱眉。

Unix类型的系统是在很早的时候就使用各种电传打字机模型开发的,在某些时候,有人决定设备在换行时应该回车。

Windows来自DOS,因此对于Windows,问题实际上是:为什么DOS使用此cr / lf序列?我猜想它与CP / M有关,而DOS正是CP / M的根源。同样,电传打字机的特定模型可能起到了作用。


嗯,很有趣。
sukhbir 2010年

1
Windows为什么不能处理以结尾的行\n,但\r\n现在仍可以继续使用?如果他们从Windows XP开始执行此操作,则现在可以开始使用\n而不是保存文件\r\n
DisgruntledGoat 2010年

1
Windows与它无关。这是应用程序的决定,大多数应用程序都会同时读取“ \ n”和“ \ r \ n”,并写入“ \ r \ n”,所以每个人都很高兴。
宫坂丽(Rei Miyasaka)2010年

2

这是最佳来源-Microsoft的答案。 为什么线路终止器为CR + LF?

该协议可以追溯到电传打字机的时代。CR代表“回车”-CR控制字符将打印头(“回车”)返回到第0列而不前进纸。LF代表“换行”-LF控制字符使纸张前进了一行,而没有移动打印头。因此,如果您想将打印头返回到第零列(准备打印下一行)并前进纸张(以便在新纸上打印),则需要CR和LF。

如果转到各种Internet协议文档,例如RFC 0821(SMTP),RFC 1939(POP),RFC 2060(IMAP)或RFC 2616(HTTP),您会发现它们都将CR + LF指定为线路终止顺序。因此,真正的问题不是“为什么CP / M,MS-DOS和Win32为什么使用CR + LF作为行终止符?” 而是“为什么其他人选择不同于这些标准文档并使用其他行终止符?”

Unix采用普通LF作为行终止顺序。如果查看stty选项,您会看到onlcr选项指定是否将LF更改为CR + LF。如果您将此设置弄错了,则会得到ststaffte文本,其中

each
    line
        begins

上一行停止的地方。因此,即使unix处于原始模式,也需要CR + LF终止行。LF之前的隐式CR是一个unix发明,可能是很经济的做法,因为它每行节省一个字节。

C语言的统一祖先将此约定带入了C语言标准,该标准仅要求“ \ n”(对LF进行编码)来终止行,这给运行时库带来了负担,可以将原始文件数据转换为逻辑行。

C语言还引入了“换行”一词来表达“通用行终止符”的概念。有人告诉我,ASCII委员会在1996年左右将字符0x0A的名称更改为“换行符”,因此混乱程度进一步提高了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.