为什么每个文本编辑器都要写一个额外的字节(UTF-8)?

Why does every text editor write an additional byte (UTF-8)?

我正在研究 Ubuntu 16.04 (Xenial Xerus)。我发现文本编辑器会向文本文件写入额外的字节 (UTF-8)。当我试图通过测试时,它给我带来了一些问题。

所以我们有一个字符串“Extra byte”,其大小为 UTF-8 中的 10 个字节。 当我尝试通过 gedit, for example, I get a file with the size = 11 byte. Also, nano 将其写入文件时,大小相同。甚至“回声“额外字节”>文件名”returns 11 个字节。

然而,当我们尝试这样的事情时:

#include <fstream>

int main(){
    std::ofstream file("filename");

    file<<"Extra byte";
    return 0;
}

或者这个:

with open("filename_py",'w+',encoding='UTF-8') as file:
    file.write('Extra byte')

我们得到大小为 10 字节的文件。为什么?

包括 gedit 和 nano 在内的许多编辑器都有在文件末尾添加换行符的功能。 std::ofstream 没有这个功能,因为它既可以用来写非文本文件,也可以用来写文本文件。

存在此功能是因为根据 POSIX 的定义,文本文件由行组成,根据定义,一行以换行符结束。

3.206 Line

A sequence of zero or more non- <newline> characters plus a terminating <newline> character.

3.403 Text File

A file that contains characters organized into zero or more lines. The lines do not contain NUL characters and none can exceed {LINE_MAX} bytes in length, including the <newline> character. Although POSIX.1-2008 does not distinguish between text files and binary files (see the ISO C standard), many utilities only produce predictable or meaningful output when operating on text files. The standard utilities that have such restrictions always specify "text files" in their STDIN or INPUT FILES sections.

您看到 newline character(在编程语言中通常表示为 \n,在 ASCII 中它是十六进制 0a,十进制 10):

$ echo 'foo' > /tmp/test.txt
$ xxd /tmp/test.txt
00000000: 666f 6f0a                                foo.

hex-dump tool xxd表示文件由4个字节组成,十六进制66(ASCII小写f),两次十六进制65(小写字母o)和换行符。

您可以使用 -n 命令行开关来禁用添加换行符:

$ echo -n 'foo' > /tmp/test.txt
$ xxd /tmp/test.txt
00000000: 666f 6f                                  foo

或者您可以改用 printf(更符合 POSIX):

$ printf 'foo' > /tmp/test.txt
$ xxd /tmp/test.txt
00000000: 666f 6f                                  foo

另见 'echo' without newline in a shell script

大多数文本编辑器还会在文件末尾添加换行符;如何防止这种情况取决于确切的编辑器(通常您可以在保存前在文件末尾使用删除)。还有各种命令行选项可以在事后删除换行符,请参阅 How can I delete a newline if it is the last character in a file?.

文本编辑器通常会添加一个换行符,因为它们处理 文本行,并且 POSIX 标准定义了 text lines end with a newline:

3.206 Line
A sequence of zero or more non- <newline> characters plus a terminating <newline> character.

另见 Why should text files end with a newline?