简短的回答:
何时使用回车(CR,\r)与换行(LF,\n)与两者(CRLF,\r\n)在文本编辑器中显示新行Windows、Mac 和 Linux:
'\r' 如何在 writer() 中的 lineterminator 中工作?
它在csv.writer() 中运行良好。这真的不是 Python、CSV 或 writer 问题。这是一个操作系统的历史差异(实际上,更准确地说是program-specific difference)可以追溯到 1960 年代左右。
或者那里发生了其他事情?
是的,就是这个。
您的记事本版本无法将回车符 (\r) 识别为用于显示新行的字符,因此不会在记事本中这样显示。其他文本编辑器,例如 Sublime Text 3,即使在 Windows 上也可能会。
直到大约 2018 年左右,Windows 和记事本都需要回车 + 换行 (\r\n)一起来显示新行。将此与仅需要 \n 的 Mac 和 Linux 进行对比。
解决方案是在 Windows 上使用 \r\n 换行,在 Mac 或 Linux 上单独使用 \n 换行。您还可以尝试不同的文本编辑器,例如 Sublime Text,查看或编辑文本文件时,或者升级您的 Windows 或记事本版本,如果可能的话,somewhere around the year 2018 Windows 记事本开始接受@ 987654351@ 单独作为有效的旧 Mac 风格的换行符。
(来自 OP 在此答案下的评论):
那为什么要给'\r\n'???
当程序员编写程序时,程序员可以让程序做程序员想让程序做的任何事情。 当 Windows 程序员制作 Windows 和记事本时,他们决定让程序在得到 \r 时不执行任何操作,如果得到 \n 则不执行任何操作,如果得到 \r\n,则执行新行 一起。就是这么简单。该程序完全按照程序员的指示去做,因为他们决定这就是他们希望程序工作的方式。因此,如果您想在 Windows 的旧版(2018 年之前)记事本中添加一个新行,您必须按照程序员的要求来获取它。 \r\n是吗。
这可以追溯到teletypewriters (read the "History" and "Representation" sections here) 和this page about "teleprinters" / "teletypewriters" / "teletype or TTY machines" 的时代:
打字机或机电打印机可以在纸上打印字符,并执行诸如将回车移回同一行的左边距(回车)等操作, 前进到下一行的同一列(换行),依此类推。
(source;强调)
电传打字机上的机械回车按钮(\r 现在在计算机上)表示:“将回车(打印头)返回到行首”(意思是:页面的最左侧),以及电传打字机上的换行机械机制(\n 现在在计算机上)的意思是:“将纸卷上一行,以便我们现在可以输入下一行。”如果没有机械换行 (\n) 操作,仅回车 (\r) 就会将机械打印头移动到页面的最左侧,并导致您在您输入的单词的顶部右回键入已经输入了! 如果没有回车机械动作(计算机上的\r),单独的换行机械动作(\n)将导致您只需在每个最右边的最后一列中输入页面上的新行,再也无法将打印头返回到页面的左侧!在机电式电传打字机上,必须使用它们两者:回车会将打印头带回页面左侧,而换行动作会移动打印前往下一行。 因此,据推测,Windows 程序员认为保持这一传统是合乎逻辑的,他们决定both 要求\r\ntogether 在一台计算机,因为这就是传统上必须在机电电传打字机上完成的方式。
阅读下文了解详情。
详情(较长的答案):
我对正在发生的事情有一些想法,但让我们来看看。我相信我们有两个问题要回答:
-
\r 是否实际存储到文件中?
- 记事本是否真的显示
\r,如果没有,为什么不呢?
所以,对于#1。让我们在 Linux 上测试一下Ubuntu 20.04(Focal Fossa):
这个程序:
#!/usr/bin/python3
import csv
data = [['fruit','quantity'], ['apple',5], ['banana',7],['mango',8]]
with open('d:\lineter.csv','w') as l:
w = csv.writer(l, delimiter='|', lineterminator='\r')
w.writerows(data)
生成此文件:d:\lineter.csv。如果我在Sublime Text 3 text editor 中打开它,我会看到:
fruit|quantity
apple|5
banana|7
mango|8
到目前为止一切顺利。我们来看看命令行中带有hexdump的字符:
hexdump -c 显示\r 字符,果然!
$ hexdump -c d\:\\lineter.csv
0000000 f r u i t | q u a n t i t y \r a
0000010 p p l e | 5 \r b a n a n a | 7 \r
0000020 m a n g o | 8 \r
0000028
您也可以使用hexdump -C 以十六进制显示字符,同样,我将文件中的\r 视为十六进制0d 字符,这是正确的。
好的,所以我在 Linux 的 VirtualBox 虚拟机中启动 Windows 10 Professional,然后在记事本中打开相同的文件,然后....它也可以工作!见截图:
但是,请注意我圈出的部分,上面写着“Macintosh (CR)”。我正在运行最新版本的 Windows 10 专业版。 我打赌你使用的是旧版本的记事本,它没有这个修复,你不会在这里说。 这是因为 33 年来记事本没有将回车符或 \r 处理为有效的行尾,因此它不会显示为这样。请参阅此处:Windows Notepad fixed after 33 years: Now it finally handles Unix, Mac OS line endings。
由于historical differences dating back to teletypewriters and Morse code(阅读此处的“历史”和“表示”部分),不同的系统决定让他们的文本编辑器以不同的方式处理行尾。来自article just above(已添加重点):
记事本以前只能识别 Windows End of Line (EOL) 字符,特别是回车符(CR、\r、0x0d)和换行符(LF、\n、0x0a)一起。。 p>
对于老式 Mac OS,EOL 字符只是回车符(CR,\r,0x0d),对于 Linux/Unix,它只是换行符(LF,\n, 0x0a)。现代 macOS,自 Mac OS X 以来,遵循 Unix 约定。
所以,我们这里的内容是在文本编辑器中显示为换行符:
-
老式 Mac: 仅限 CR (
\r)
-
Windows 记事本直到 ~2018: CR 和 LF 一起 (
\r\n)
-
Linux: 仅限 LF (
\n)
-
现代 Mac: 仅限 LF (
\n)
-
现代 Windows 记事本(2018 年及以后):上述任何场景。
因此,对于 Windows,只需始终使用 \r\n 换行,对于 Mac 或 Linux,只需坚持始终使用 \n 作为换行符,除非您试图保证文件的老式(即 2019 年之前 :))Windows 兼容性,在这种情况下,您也应该使用 \r\n 作为换行符。
注意,对于 Sublime Text 3,我只是在 Preferences → Settings 中搜索了首选项,发现了这个设置:
// Determines what character(s) are used to terminate each line in new files.
// Valid values are 'system' (whatever the OS uses), 'windows' (CRLF) and
// 'unix' (LF only).
"default_line_ending": "system",
因此,要对运行 Sublime Text 的任何操作系统使用约定,默认为“系统”。但是,要在 Sublime Text 中编辑和保存文件时强制 'windows' (CRLF) 行结束,请使用以下命令:
"default_line_ending": "windows",
要强制 Unix(Mac 和 Linux)仅 LF 行尾设置,请使用:
"default_line_ending": "unix",
在记事本编辑器中,我找不到要配置的此类设置。它是一个简单的编辑器,33 年来只支持 Windows 行尾。
补充阅读:
- https://en.wikipedia.org/wiki/Teleprinter
- https://en.wikipedia.org/wiki/Newline#History
- Is a new line = \n OR \r\n?
- Why does Windows use CR LF?
- [我还需要阅读和学习]Unix & Linux: Why does Linux use LF as the newline character?
- [我还需要阅读和学习]Retrocomputing: Why is Windows using CR+LF and Unix just LF when Unix is the older system?