我有一个文本文件(通过在linux中重定向find
命令的输出而创建)。该文件的前4行如下所示:
/home/uujjwal/datasets/pedestrian/INRIAPerson/Train/pos/person_299.png
/home/uujjwal/datasets/pedestrian/INRIAPerson/Train/pos/crop001540.png
/home/uujjwal/datasets/pedestrian/INRIAPerson/Train/pos/crop001044.png
/home/uujjwal/datasets/pedestrian/INRIAPerson/Train/pos/person_195.png
我使用以下内容在Python 2.7中将其作为完整字符串阅读:
fid = open('filelist.txt', 'r').read() # Successful
当我尝试在python 3.5中执行相同操作时,我收到以下错误:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf4 in position 141: invalid continuation byte
我意识到了python 3.5和2.7之间的差异,并尝试指定ascii
编码。我使用chardet包确定了ascii
编码,如下所示(使用其命令行工具):
[uujjwal@rotanev pos]$ chardetect /home/uujjwal/datasets/pedestrian/INRIAPerson/Train/pos/filelist.txt
/home/uujjwal/datasets/pedestrian/INRIAPerson/Train/pos/filelist.txt: ascii with confidence 1.0
因此我做了以下事情:
fstr = open(annotation_file, 'r', encoding='ascii').read() #Failure
这给出了以下错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf4 in position 141: ordinal not in range(128)
我想明白:
注意:我没有以任何方式手动修改文本文件。
附录
我检查了文件的全部内容。它有字母az,AZ,0-9(所有具有众所周知的ASCII值)正斜杠(/)(扩展ASCII值47 )和下划线(_)(扩展ASCII值95 )以及点(。)(扩展的ASCII值为46 )。它还有换行符(**扩展ASCII值为10 **)。文件中没有其他字符。
字节0xf4对应于244的扩展ASCII(段落符号)。这是因为通过重定向find
命令的输出来创建文件而不能存在。
答案 0 :(得分:3)
该文件不是ASCII编码的。 Chardet使用启发式方法并不测试整个文件,并且在这里弄错了。它也不是UTF-8,由另一个错误证明。
Chardet无法总是说出它在看什么:
>>> chardet.detect((('This mostly ASCII, with a hidden surprise' * 20) + 'hellø').encode('utf8'))
{'encoding': 'ISO-8859-2', 'confidence': 0.7225312698370376}
ø
只编码为两个字节:
>>> 'ø'.encode('utf8')
b'\xc3\xb8'
这不足以让chardet做出正确的电话。
使用其他编解码器打开文件。什么编解码器确实很难说;在Latin-1和Windows Codepage 1252中,0xF4是ô
字符,它不会立即显示它适合您显示的最小数据(位置141将在前4行内)
请注意,在Python 2中,您实际上只读取了文件的二进制内容,而没有将数据解码为Unicode文本,这就是您不会在那里得到错误的原因。
请注意,没有“扩展ASCII”这样的东西。术语exists但是是伪造的,没有带有该名称的标准,并且几乎用于任何作为ASCII超集的8位编解码器。字节值0xF4表示不同编解码器中的不同内容;在IBM 775 codepage中,它是Paragraph (Pilcrow) symbol,就像在代码页850,856,857和858中一样。