Python 加载 'utf-16' 文件无法解码 '\u0153'
Python loading 'utf-16' file can't decode '\u0153'
我有一个编码为 utf-16
的文本文件,它会为以下字符抛出异常:'\u0153'
.
UnicodeEncodeError: 'charmap' codec can't encode character '\u0153' in position
我正在使用一个非常简单的脚本来加载文件,而且我还尝试了 忽略 错误但无济于事。我做错了什么?
with open(filename, "r", encoding="utf-16", errors='replace') as data_file:
print(data_file.read())
这是破坏文件的一部分:
["Xinhua","Ürümqi"]
编辑:
不知道为什么我的问题被误解了。希望这是更好的形式。
我应该如何用 Python 阅读这个文件?
Sample file link(UTF-16-LE 文件)包含:
["Xinhua","Ürümqi"]
为什么这段代码不起作用?
with open(filename, "r", encoding="utf-16", errors='replace') as data_file:
print(data_file.read())
最初难倒您的异常是因为您在终端仿真器中 运行 Python(或者可能 "console window" 是一个更熟悉的术语?)无法显示Unicode 中的所有字符。要解决这个问题,您需要让自己拥有一个支持 Unicode 的终端仿真器,然后确保 Python 知道 它是 运行 在一个支持 Unicode 的终端仿真器中。如果您不知道该怎么做,请在 superuser.com 上提出一个新问题,并指定您的操作系统。
我的终端模拟器 可以 显示所有 Unicode 字符,假设所有必要的字体都可用,并且 Python 知道这一点,所以我可以这样做并且没有得到异常:
>>> with open("countryCity2.json", "r", encoding="utf-16") as f:
... x = f.read()
...
>>> print(x)
["Xinhua","Ürümqi"]
但是,这不是您唯一的问题。您的输入文件的编码已损坏。 Ürümqi
不是在任何语言中都有意义的字符序列。但是,它符合已从传统编码转换为 UTF-8,然后又错误地转换为 Unicode 编码 的文本特征 mojibake 模式。我们可以通过将它 1:1 转换为字节并查看我们是否获得有效的 UTF-8 字节序列来测试它:
>>> print(x.encode("iso-8859-1").decode("utf-8"))
["Xinhua","Ürümqi"]
"Ürümqi" is a real word and would plausibly appear in conjunction with "Xinhua"。另外,如果文本没有被错误转换为 UTF-8,我们会看到一个异常:
>>> "Ürümqi".encode("iso-8859-1").decode("utf-8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xdc in position 0:
invalid continuation byte
假设成立
在一个必须处理大量文件的程序中,这些文件的编码可能会或可能不会以这种方式被破坏,我会这样做:
for fname in input_files:
with open(fname, "r", encoding="utf-16") as f:
contents = f.read()
try:
contents = contents.encode("iso-8859-1").decode("utf-8")
except (UnicodeEncodeError, UnicodeDecodeError):
pass
process_file(fname, contents)
我在这里使用 ISO 8859.1 编码 而不是 因为文本实际上是或曾经使用该编码,但是因为 Python 的 iso-8859-1
codec是从字符U+0000..U+00FF到字节0x00..0xFF的恒等映射。 (从技术上讲,这意味着它实现了 IANA ISO_8859-1:1987 而不是原始的 ECMA-94:1985 代码页,后者未定义 0x00..0x1F 和 0x7F..0x9F 范围。)也就是说,
>>> "".join(chr(c) for c in range(256)).encode('iso-8859-1') == bytes(range(256))
True
因此,任何时候您的二进制数据被错误转换为 Unicode,您都可以使用 .encode('iso-8859-1')
恢复原始数据。
注意: 以上所有代码片段都是 Python 3.
我的答案在 Python3.5 上工作并忽略所有变形的字符,所以目标是在 try 块中打印正确的字符,在块中除了你可以在块中使用 pass除了,或者打印它们并使用 encode() 对它们进行编码
from codecs import open
with open("C:/test2/trans1", "r", "utf-8") as f:
lines = f.readlines()
f.close()
for ligne in lines:
try:
print(ligne.rstrip())
except UnicodeEncodeError:
print(ligne.rstrip().encode())
我有一个编码为 utf-16
的文本文件,它会为以下字符抛出异常:'\u0153'
.
UnicodeEncodeError: 'charmap' codec can't encode character '\u0153' in position
我正在使用一个非常简单的脚本来加载文件,而且我还尝试了 忽略 错误但无济于事。我做错了什么?
with open(filename, "r", encoding="utf-16", errors='replace') as data_file:
print(data_file.read())
这是破坏文件的一部分:
["Xinhua","Ürümqi"]
编辑: 不知道为什么我的问题被误解了。希望这是更好的形式。
我应该如何用 Python 阅读这个文件?
Sample file link(UTF-16-LE 文件)包含:
["Xinhua","Ürümqi"]
为什么这段代码不起作用?
with open(filename, "r", encoding="utf-16", errors='replace') as data_file:
print(data_file.read())
最初难倒您的异常是因为您在终端仿真器中 运行 Python(或者可能 "console window" 是一个更熟悉的术语?)无法显示Unicode 中的所有字符。要解决这个问题,您需要让自己拥有一个支持 Unicode 的终端仿真器,然后确保 Python 知道 它是 运行 在一个支持 Unicode 的终端仿真器中。如果您不知道该怎么做,请在 superuser.com 上提出一个新问题,并指定您的操作系统。
我的终端模拟器 可以 显示所有 Unicode 字符,假设所有必要的字体都可用,并且 Python 知道这一点,所以我可以这样做并且没有得到异常:
>>> with open("countryCity2.json", "r", encoding="utf-16") as f:
... x = f.read()
...
>>> print(x)
["Xinhua","Ürümqi"]
但是,这不是您唯一的问题。您的输入文件的编码已损坏。 Ürümqi
不是在任何语言中都有意义的字符序列。但是,它符合已从传统编码转换为 UTF-8,然后又错误地转换为 Unicode 编码 的文本特征 mojibake 模式。我们可以通过将它 1:1 转换为字节并查看我们是否获得有效的 UTF-8 字节序列来测试它:
>>> print(x.encode("iso-8859-1").decode("utf-8"))
["Xinhua","Ürümqi"]
"Ürümqi" is a real word and would plausibly appear in conjunction with "Xinhua"。另外,如果文本没有被错误转换为 UTF-8,我们会看到一个异常:
>>> "Ürümqi".encode("iso-8859-1").decode("utf-8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xdc in position 0:
invalid continuation byte
假设成立
在一个必须处理大量文件的程序中,这些文件的编码可能会或可能不会以这种方式被破坏,我会这样做:
for fname in input_files:
with open(fname, "r", encoding="utf-16") as f:
contents = f.read()
try:
contents = contents.encode("iso-8859-1").decode("utf-8")
except (UnicodeEncodeError, UnicodeDecodeError):
pass
process_file(fname, contents)
我在这里使用 ISO 8859.1 编码 而不是 因为文本实际上是或曾经使用该编码,但是因为 Python 的 iso-8859-1
codec是从字符U+0000..U+00FF到字节0x00..0xFF的恒等映射。 (从技术上讲,这意味着它实现了 IANA ISO_8859-1:1987 而不是原始的 ECMA-94:1985 代码页,后者未定义 0x00..0x1F 和 0x7F..0x9F 范围。)也就是说,
>>> "".join(chr(c) for c in range(256)).encode('iso-8859-1') == bytes(range(256))
True
因此,任何时候您的二进制数据被错误转换为 Unicode,您都可以使用 .encode('iso-8859-1')
恢复原始数据。
注意: 以上所有代码片段都是 Python 3.
我的答案在 Python3.5 上工作并忽略所有变形的字符,所以目标是在 try 块中打印正确的字符,在块中除了你可以在块中使用 pass除了,或者打印它们并使用 encode() 对它们进行编码
from codecs import open
with open("C:/test2/trans1", "r", "utf-8") as f:
lines = f.readlines()
f.close()
for ligne in lines:
try:
print(ligne.rstrip())
except UnicodeEncodeError:
print(ligne.rstrip().encode())