打开文件读取 Python 时应该使用 utf8 还是 utf-8-sig?
Should I use utf8 or utf-8-sig when opening a file to read in Python?
我一直用'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(' ')
但是,上面的代码在 for 'f2':
的行引入了一个额外的 '\ufeff' 代码
columns = line.split(' ')
现在第[0]列包含这个字符,而'line'没有这个字符。这是为什么?然后我切换到'utf-8-sig',问题就没有了。
然而,读取 'f' 和 'columns' 的第一个文件根本没有这个问题,即使只有 'encoding=utf8'。都是纯文本文件。
所以我有两个问题:
- 我正在使用 Python3,在读取文件时,我是否应该始终使用 'utf-8-sig' 以确保安全?
- 为什么 'line' 不包含此附加代码,但 'columns' 包含它?
UTF-8 编码的文件可以写上一个表明它是 UTF-8 的签名。此签名代码称为“字节顺序标记”(或 BOM)并具有 Unicode 代码点值 U+FEFF。如果在十六进制编辑器中查看包含 BOM 的文件,该文件将以十六进制字节 EF BB BF
开头。在使用非 UTF-8 编码的文本编辑器中查看时,它们通常显示为 
,但这取决于编码。
'utf-8-sig'
编解码器可以读取使用和不使用起始 BOM 签名编写的 UTF-8 编码文件,如果存在则将其删除。
仅当您想要在文件开头写入 UTF-8 BOM 时,才使用 'utf-8-sig'
写入文件。一些(通常是 Windows)程序,例如 Excel 在读取文本文件时,如果文件包含 UTF-8 则期望 BOM,否则假定本地化编码。其他程序可能不需要 BOM,可以将其作为额外字符读取,因此选择权在您手中。
所以对于你的两个问题:
I am using Python3 and when reading a file, should I always use 'utf-8-sig' to be safe?
是的,它将删除 BOM(如果存在)。
Why doesn't 'line' contain this additional code, but 'columns' contains it?
line.strip()
不会删除 \ufeff
,因此我无法重现您的声明。如果使用 utf8
打开带 BOM 编码的 UTF-8 文件,第一个字符应为 \ufeff
。您是否使用 print
来显示该行?如果打印 \ufeff
是空白字符:
>>> line = '\ufeffabc'
>>> line
'\ufeffabc'
>>> print(line)
abc
>>> print(line.strip())
abc
>>> line.strip()
'\ufeffabc'
我一直用'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(' ')
但是,上面的代码在 for 'f2':
的行引入了一个额外的 '\ufeff' 代码columns = line.split(' ')
现在第[0]列包含这个字符,而'line'没有这个字符。这是为什么?然后我切换到'utf-8-sig',问题就没有了。
然而,读取 'f' 和 'columns' 的第一个文件根本没有这个问题,即使只有 'encoding=utf8'。都是纯文本文件。
所以我有两个问题:
- 我正在使用 Python3,在读取文件时,我是否应该始终使用 'utf-8-sig' 以确保安全?
- 为什么 'line' 不包含此附加代码,但 'columns' 包含它?
UTF-8 编码的文件可以写上一个表明它是 UTF-8 的签名。此签名代码称为“字节顺序标记”(或 BOM)并具有 Unicode 代码点值 U+FEFF。如果在十六进制编辑器中查看包含 BOM 的文件,该文件将以十六进制字节 EF BB BF
开头。在使用非 UTF-8 编码的文本编辑器中查看时,它们通常显示为 
,但这取决于编码。
'utf-8-sig'
编解码器可以读取使用和不使用起始 BOM 签名编写的 UTF-8 编码文件,如果存在则将其删除。
仅当您想要在文件开头写入 UTF-8 BOM 时,才使用 'utf-8-sig'
写入文件。一些(通常是 Windows)程序,例如 Excel 在读取文本文件时,如果文件包含 UTF-8 则期望 BOM,否则假定本地化编码。其他程序可能不需要 BOM,可以将其作为额外字符读取,因此选择权在您手中。
所以对于你的两个问题:
I am using Python3 and when reading a file, should I always use 'utf-8-sig' to be safe?
是的,它将删除 BOM(如果存在)。
Why doesn't 'line' contain this additional code, but 'columns' contains it?
line.strip()
不会删除 \ufeff
,因此我无法重现您的声明。如果使用 utf8
打开带 BOM 编码的 UTF-8 文件,第一个字符应为 \ufeff
。您是否使用 print
来显示该行?如果打印 \ufeff
是空白字符:
>>> line = '\ufeffabc'
>>> line
'\ufeffabc'
>>> print(line)
abc
>>> print(line.strip())
abc
>>> line.strip()
'\ufeffabc'