在 Python 中打开文件读取时应该使用 utf8 还是 utf-8-sig?

mar*_*lon 2 python utf-8 python-3.x

我一直使用“utf8”来读取文件:

 with open(filename, 'r', encoding='utf8') as f, open(filename2, 'r', encoding='utf8') as f2:
      for line in f:
          line = line.strip()
          columns = line.split(' ')
       for line in f2:
          line = line.strip()
          columns = line.split(' ')
Run Code Online (Sandbox Code Playgroud)

然而,上面的代码在 for 'f2' 行引入了额外的 '\ufeff' 代码:

columns = line.split(' ')
Run Code Online (Sandbox Code Playgroud)

现在 columns[0] 包含这个字符,而 'line' 没有这个字符。这是为什么?然后我切换到“utf-8-sig”,问题就消失了。

但是,读取“f”和“列”的第一个文件根本不存在此问题,即使仅使用“encoding=utf8”也是如此。两者都是纯文本文件。

所以我有两个问题:

  1. 我正在使用 Python3,在读取文件时,我应该始终使用“utf-8-sig”以确保安全吗?
  2. 为什么“行”不包含此附加代码,但“列”包含它?

Mar*_*nen 5

UTF-8 编码的文件可以使用表明它是 UTF-8 的签名来编写。该签名代码称为“字节顺序标记”(或 BOM),具有 Unicode 代码点值 U+FEFF。如果在十六进制编辑器中查看包含 BOM 的文件,该文件将以十六进制字节开头EF BB BF。当在使用非 UTF-8 编码的文本编辑器中查看时,它们通常显示为,\xc3\xaf\xc2\xbb\xc2\xbf但这取决于编码。

\n

\'utf-8-sig\'解码器可以读取带有或不带有起始 BOM 签名的 UTF-8 编码文件,如果存在,则会将其删除。

\n

仅当您希望在文件开头写入 UTF-8 BOM 时才用于\'utf-8-sig\'写入文件。某些(通常是 Windows)程序(例如 Excel)在读取文本文件时,如果文件包含 UTF-8,则需要 BOM,否则采用本地化编码。其他程序可能不需要 BOM,并且可以将其作为额外字符读取,因此选择权在您手中。

\n

所以对于你的两个问题:

\n
\n

我正在使用 Python3,在读取文件时,我应该始终使用 \'utf-8-sig\' 以确保安全吗?

\n
\n

是的,如果存在 BOM,它将删除。

\n
\n

为什么“行”不包含此附加代码,但“列”包含它?

\n
\n

line.strip()没有删除,\\ufeff所以我无法重现您的声明。如果打开带有 BOM 编码的 UTF-8 文件,utf8第一个字符应该是\\ufeff. 你用的是print显示线吗? \\ufeff如果打印的话是空白字符:

\n
>>> line = \'\\ufeffabc\'\n>>> line\n\'\\ufeffabc\'\n>>> print(line)\n abc\n>>> print(line.strip())\n abc\n>>> line.strip()\n\'\\ufeffabc\'\n
Run Code Online (Sandbox Code Playgroud)\n