使用 xlrd 打开 Excel 文件时出现编码错误
Encoding error when opening an Excel file with xlrd
我正在尝试使用 xlrd 打开 Excel 文件 (.xls)。这是我正在使用的代码的摘要:
import xlrd
workbook = xlrd.open_workbook('thefile.xls')
这适用于大多数文件,但不适用于我从特定组织获得的文件。当我尝试打开来自该组织的 Excel 文件时出现的错误如下。
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/__init__.py", line 435, in open_workbook
ragged_rows=ragged_rows,
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/book.py", line 116, in open_workbook_xls
bk.parse_globals()
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/book.py", line 1180, in parse_globals
self.handle_writeaccess(data)
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/book.py", line 1145, in handle_writeaccess
strg = unpack_unicode(data, 0, lenlen=2)
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/biffh.py", line 303, in unpack_unicode
strg = unicode(rawstrg, 'utf_16_le')
File "/app/.heroku/python/lib/python2.7/encodings/utf_16_le.py", line 16, in decode
return codecs.utf_16_le_decode(input, errors, True)
UnicodeDecodeError: 'utf16' codec can't decode byte 0x40 in position 104: truncated data
这看起来好像 xlrd 正在尝试打开一个 Excel 文件编码不是 UTF-16。我怎样才能避免这个错误?文件是否以有缺陷的方式写入,或者是否只是一个特定的字符导致了问题?如果我打开并重新保存 Excel 文件,xlrd 可以毫无问题地打开该文件。
我试过用不同的编码覆盖打开工作簿,但这也不起作用。
我要打开的文件可以在这里找到:
https://dl.dropboxusercontent.com/u/6779408/Whosebug/AEPUsageHistoryDetail_RequestID_00183816.xls
他们使用什么来生成该文件?
他们正在使用一些 Java Excel API(见下文,link here),可能在 IBM 大型机或类似设备上。
从堆栈跟踪中,写入访问信息无法解码为 Unicode,因为 @ 字符。
有关 XLS 文件格式的写入访问信息的更多信息,请参阅 5.112 WRITEACCESS or Page 277。
此字段包含保存文件的用户的用户名。
import xlrd
dump = xlrd.dump('thefile.xls')
运行 xlrd.dump 原始文件给出
36: 005c WRITEACCESS len = 0070 (112)
40: d1 81 a5 81 40 c5 a7 83 85 93 40 c1 d7 c9 40 40 ????@?????@???@@
56: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
72: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
88: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
104: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
120: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
136: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
在使用 Excel 或我的 LibreOffice Calc 重新保存后,写访问信息被类似
的内容覆盖
36: 005c WRITEACCESS len = 0070 (112)
40: 04 00 00 43 61 6c 63 20 20 20 20 20 20 20 20 20 ?~~Calc
56: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
72: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
88: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
104: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
136: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
根据编码为 40 的空格,我认为编码是 EBCDIC,当我们将 d1 81 a5 81 40 c5 a7 83 85 93 40 c1 d7 c9 40 40
转换为 EBCDIC 时,我们得到 Java Excel API
.
所以是的,在 BIFF8 和更高版本的情况下,文件以有缺陷的方式写入,它应该是一个 unicode 字符串,而在 BIFF3 到 BIFF5 中,它应该是 CODEPAGE 信息中编码的字节字符串,它是
152: 0042 CODEPAGE len = 0002 (2)
156: 12 52 ?R
1252 是 Windows CP-1252 (Latin I) (BIFF4-BIFF5),它不是 EBCDIC_037.
xlrd 尝试使用 unicode,这意味着它确定文件的版本为 BIFF8。
在这种情况下,您有两个选择
先修复文件再用 xlrd 打开它。您可以使用转储检查不是标准输出的文件,然后如果是这种情况,您可以使用 xlutils.save 或其他库覆盖写入访问信息。
修补程序 xlrd 以处理您的特殊情况,在 handle_writeaccess
添加一个 try 块并在 unpack_unicode 失败时将 strg 设置为空字符串。
以下片段
def handle_writeaccess(self, data):
DEBUG = 0
if self.biff_version < 80:
if not self.encoding:
self.raw_user_name = True
self.user_name = data
return
strg = unpack_string(data, 0, self.encoding, lenlen=1)
else:
try:
strg = unpack_unicode(data, 0, lenlen=2)
except:
strg = ""
if DEBUG: fprintf(self.logfile, "WRITEACCESS: %d bytes; raw=%s %r\n", len(data), self.raw_user_name, strg)
strg = strg.rstrip()
self.user_name = strg
和
workbook=xlrd.open_workbook('thefile.xls',encoding_override="cp1252")
似乎打开文件成功。
没有编码覆盖它会抱怨 ERROR *** codepage 21010 -> encoding 'unknown_codepage_21010' -> LookupError: unknown encoding: unknown_codepage_21010
这对我有用。
import xlrd
my_xls = xlrd.open_workbook('//myshareddrive/something/test.xls',encoding_override="gb2312")
我正在尝试使用 xlrd 打开 Excel 文件 (.xls)。这是我正在使用的代码的摘要:
import xlrd
workbook = xlrd.open_workbook('thefile.xls')
这适用于大多数文件,但不适用于我从特定组织获得的文件。当我尝试打开来自该组织的 Excel 文件时出现的错误如下。
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/__init__.py", line 435, in open_workbook
ragged_rows=ragged_rows,
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/book.py", line 116, in open_workbook_xls
bk.parse_globals()
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/book.py", line 1180, in parse_globals
self.handle_writeaccess(data)
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/book.py", line 1145, in handle_writeaccess
strg = unpack_unicode(data, 0, lenlen=2)
File "/app/.heroku/python/lib/python2.7/site-packages/xlrd/biffh.py", line 303, in unpack_unicode
strg = unicode(rawstrg, 'utf_16_le')
File "/app/.heroku/python/lib/python2.7/encodings/utf_16_le.py", line 16, in decode
return codecs.utf_16_le_decode(input, errors, True)
UnicodeDecodeError: 'utf16' codec can't decode byte 0x40 in position 104: truncated data
这看起来好像 xlrd 正在尝试打开一个 Excel 文件编码不是 UTF-16。我怎样才能避免这个错误?文件是否以有缺陷的方式写入,或者是否只是一个特定的字符导致了问题?如果我打开并重新保存 Excel 文件,xlrd 可以毫无问题地打开该文件。
我试过用不同的编码覆盖打开工作簿,但这也不起作用。
我要打开的文件可以在这里找到:
https://dl.dropboxusercontent.com/u/6779408/Whosebug/AEPUsageHistoryDetail_RequestID_00183816.xls
他们使用什么来生成该文件?
他们正在使用一些 Java Excel API(见下文,link here),可能在 IBM 大型机或类似设备上。
从堆栈跟踪中,写入访问信息无法解码为 Unicode,因为 @ 字符。
有关 XLS 文件格式的写入访问信息的更多信息,请参阅 5.112 WRITEACCESS or Page 277。
此字段包含保存文件的用户的用户名。
import xlrd
dump = xlrd.dump('thefile.xls')
运行 xlrd.dump 原始文件给出
36: 005c WRITEACCESS len = 0070 (112)
40: d1 81 a5 81 40 c5 a7 83 85 93 40 c1 d7 c9 40 40 ????@?????@???@@
56: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
72: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
88: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
104: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
120: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
136: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@
在使用 Excel 或我的 LibreOffice Calc 重新保存后,写访问信息被类似
的内容覆盖 36: 005c WRITEACCESS len = 0070 (112)
40: 04 00 00 43 61 6c 63 20 20 20 20 20 20 20 20 20 ?~~Calc
56: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
72: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
88: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
104: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
136: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
根据编码为 40 的空格,我认为编码是 EBCDIC,当我们将 d1 81 a5 81 40 c5 a7 83 85 93 40 c1 d7 c9 40 40
转换为 EBCDIC 时,我们得到 Java Excel API
.
所以是的,在 BIFF8 和更高版本的情况下,文件以有缺陷的方式写入,它应该是一个 unicode 字符串,而在 BIFF3 到 BIFF5 中,它应该是 CODEPAGE 信息中编码的字节字符串,它是
152: 0042 CODEPAGE len = 0002 (2)
156: 12 52 ?R
1252 是 Windows CP-1252 (Latin I) (BIFF4-BIFF5),它不是 EBCDIC_037.
xlrd 尝试使用 unicode,这意味着它确定文件的版本为 BIFF8。
在这种情况下,您有两个选择
先修复文件再用 xlrd 打开它。您可以使用转储检查不是标准输出的文件,然后如果是这种情况,您可以使用 xlutils.save 或其他库覆盖写入访问信息。
修补程序 xlrd 以处理您的特殊情况,在
handle_writeaccess
添加一个 try 块并在 unpack_unicode 失败时将 strg 设置为空字符串。
以下片段
def handle_writeaccess(self, data):
DEBUG = 0
if self.biff_version < 80:
if not self.encoding:
self.raw_user_name = True
self.user_name = data
return
strg = unpack_string(data, 0, self.encoding, lenlen=1)
else:
try:
strg = unpack_unicode(data, 0, lenlen=2)
except:
strg = ""
if DEBUG: fprintf(self.logfile, "WRITEACCESS: %d bytes; raw=%s %r\n", len(data), self.raw_user_name, strg)
strg = strg.rstrip()
self.user_name = strg
和
workbook=xlrd.open_workbook('thefile.xls',encoding_override="cp1252")
似乎打开文件成功。
没有编码覆盖它会抱怨 ERROR *** codepage 21010 -> encoding 'unknown_codepage_21010' -> LookupError: unknown encoding: unknown_codepage_21010
这对我有用。
import xlrd
my_xls = xlrd.open_workbook('//myshareddrive/something/test.xls',encoding_override="gb2312")