可移植行结束符(换行符)
Portable end of line (newline)
这是一个令人不快的惊喜,'n'
取代了"rn"
在Windows上,我不知道。(我猜它也被替换在Mac上…)
是否有一种简单的方法来确保Linux, Mac和Windows用户可以轻松地交换文本文件?
我的意思是:不以二进制模式编写文件或自己测试和替换行尾字符(或使用一些第三方程序/代码)。这个问题影响了我的c++程序执行文本文件I/o。
为与其他答案部分重叠而道歉,但为了完整性:
误解: endl
'更可移植',因为它根据平台约定编写行结束符。
真相: endl
定义为将n
写入流,然后调用flush
。所以实际上你几乎不会想用它。无论您使用的是os<<endl
、os<<'n'
还是fputs("n",file)
,所有写入文本模式流的n
都会在后台被CRT隐式地转换为rn
。
误解:你应该以文本模式打开文件来写文本,以二进制模式打开文件来写二进制数据。
真相:文本模式之所以存在,首先是因为以前的文件系统区分了文本文件和二进制文件。在我所知道的任何一个平台上都不再是这样了。您也可以将文本写入二进制打开的文件,您只是失去了自动的n
->rn
在Windows上的转换。然而,这种转换弊大于利。除此之外,它使您的代码在不同的平台上表现不同,并且tell/seek
的使用变得有问题。因此,最好使用避免这种自动转换。请注意POSIX 不区分二进制模式和文本模式。
如何做文本:在二进制模式下打开所有内容,并使用普通的n
。您还需要考虑编码问题。标准化UTF-8以确保unicode的正确性。在内部使用UTF-8编码的窄字符串,而不是wchar_t
,这在不同的平台上是不同的。您的代码将变得更容易移植。
提示:可以强制MSVC默认以二进制模式打开所有文件。它应该是这样工作的:
#include <stdio.h>
#include <iostream>
int main() {
_fmode = _O_BINARY;
std::ofstream f("a.txt"); // opens in binary mode
}
EDIT:截至2021年,Windows 10记事本可以理解UNIX行结束符。
问题根本不在于endl
,而是文本流根据系统的标准重新格式化换行符。
如果你不想这样,干脆不要使用文本流——使用二进制流。也就是说,打开带有ios::binary
标志的文件。
这是任何体面的文本编辑器所做的(但是,Windows上的默认notepad.exe
是而不是一个体面的文本编辑器,并且不能正确处理Unix换行符)。
如果你真的只想要一个ASCII LF,最简单的方法是以二进制模式打开文件:在非二进制模式下,n被特定平台的行尾序列替换(例如,它可能被LF/CR或CR/LF序列替换;在unix上,它通常只是LF)。在二进制模式下不会这样做。关闭替换也是二进制模式的唯一效果。
顺便说一句,使用endl相当于写一个n,然后刷新流。通常的非预期刷新会成为主要的性能问题。因此,endl应该很少使用,并且只在需要刷新时使用。
- 如何防止clang格式在流运算符调用之间添加换行符<<
- C/C++ - 查询平台相关的换行符(用于内存映射文件)
- 在 Stream C++ 文本之前有一个额外的换行符
- 流:CSV 文件中的换行符
- 如何在三元条件运算符中添加换行符和连接? :在 C++ 中
- Clang-格式:在多行语句之后的换行符上打开大括号
- 在输出流中插入换行符
- 防止控制台在通道字符(在 c++ 中)中输入空格(即空格、制表符和换行符)
- QProcess::readAllStandardOutput() 和换行符
- 如果有换行符,clang 格式不会附加大括号
- 提取后返回换行符的C++istream.get()
- 如何在出现换行符之前将多个整数作为输入?
- 正则表达式 获取两个换行符之间的文本
- 包含换行符分隔的单词的文件和C++中这些单词的字符串向量的大小是否相同?
- 在字符串中输入换行符
- 从文本文件中读取数据并删除所有换行符空格,并在 C++ 控制台中显示
- 读取带引号的 CSV 数据,不带换行符作为结束行
- 检查流是否以换行符结束
- Boost::asio::async_read返回文件结束错误的换行符
- 用换行符结束数组输入