我正在尝试使用python脚本从中国服务提供商处下载文件(我自己不是来自中国)。提供程序给我一个.zip文件,其中包含一个似乎在其名称中包含中文字符的文件。这似乎导致zipfile模块被禁止。
代码:
import zipfile
f = "/path/to/zip_file.zip"
if zipfile.is_zipfile(f):
fz = zipfile.ZipFile(f, 'r')
zipfile本身不包含任何非ASCII字符,但其中包含文件。当我运行上面的脚本时,我得到以下异常:
Traceback (most recent call last): File "./temp.py", line 9, in <module>
fz = zipfile.ZipFile(f, 'r') File "/usr/lib/python2.7/zipfile.py", line 770, in __init__
self._RealGetContents() File "/usr/lib/python2.7/zipfile.py", line 859, in _RealGetContents
x.filename = x._decodeFilename() File "/usr/lib/python2.7/zipfile.py", line 379, in _decodeFilename
return self.filename.decode('utf-8') File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0xbd in position 30: invalid start byte
我已经尝试查看许多类似问题的答案:
如果我错了,请纠正我,但它看起来像open issue with the zipfile module。
我如何解决这个问题?是否有任何替代模块来处理我应该使用的zipfiles?还是其他任何解决方案?
TIA。
编辑: 我可以使用linux命令行实用程序“unzip”完美地访问/解压缩同一个文件。
答案 0 :(得分:3)
Python 2.x(2.7)和Python 3.x在模块zipfile中处理非utf-8文件名的方式有点不同。
首先,他们都检查文件的ZipInfo.flag_bits,如果ZipInfo.flag_bits&amp; 0x800,文件名将用utf-8解码。
如果上面的检查为False,则在Python 2.x中,将返回名称的字节字符串;在Python 3.x中,模块将使用编码cp437解码文件并返回解码结果。当然,模块不会知道两个Python版本中文件名的真正编码。
因此,假设您从ZipInfo对象或zipfile.namelist方法获得了文件名,并且您已经知道文件名是使用XXX编码进行编码的。这些是你获得正确的unicode文件名的方法:
# in python 2.x
filename = filename.decode('XXX')
# in python 3.x
filename = filename.encode('cp437').decode('XXX')
答案 1 :(得分:1)
ZIP文件无效。它有一个标志,表示其中的文件名被编码为UTF-8,但它们实际上不是;它们包含无效的UTF-8字节序列。也许他们是GBK?也许别的什么?也许是一些邪恶的不一致混合物?遗憾的是,ZIP工具在处理非ASCII文件名时非常差。
快速解决方法可能是替换解码文件名的库函数。这是一个猴子补丁,因为没有一种简单的方法将自己的ZipInfo类注入ZipFile,但是:
zipfile.ZipInfo._decodeFilename = lambda self: self.filename
将禁用对文件名进行解码的尝试,并始终返回具有字节字符串filename
属性的ZipInfo,您可以以适当的方式手动解码/处理。
答案 2 :(得分:1)
最近我遇到了同样的问题。这是我的理论。希望对你有用。
null pointer exception
更新:您可以使用以下更简单的解决方案import shutil
import zipfile
f = zipfile.ZipFile('/path/to/zip_file.zip', 'r')
for fileinfo in f.infolist():
filename = fileinfo.filename.encode('cp437').decode('gbk')
outputfile = open(filename, "wb")
shutil.copyfileobj(f.open(fileinfo.filename), outputfile)
outputfile.close()
f.close()
:
pathlib
答案 3 :(得分:0)
这段代码怎么样?
for(int i=0;i<noOfCols1;i++)
{
for(int j=1;j<=noOfRows1;j++)
{
value1 = formatter.formatCellValue(sheet1.getRow(j).getCell(i));
for(int m=1;m<=noOfRows2;m++)
{
value2 = formatter.formatCellValue(sheet2.getRow(m).getCell(i));
value1= value1.trim();
value2=value2.trim();
int value2Position = sheet2.getRow(m).getCell(i).getRowIndex();
if(!positions.contains(value2Position))
{
if(value1.contentEquals(value2))
{
positions.add(value2Position);
matched = true;
}
else{
matched = false;
}
}
if(matched==true)
{
break;
}
}
if(matched == false)
{
int k=1;
if(cFilledPositions.isEmpty())
{
try{
isEmpty = checkIfRowIsEmpty(sheet,k,formatter);
if(isEmpty)
{
rowHead = sheet.createRow(k);
}
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e){
try{
rowHead = sheet.createRow(k);
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e1){
}
}
}
else
{
int l = cFilledPositions.size()-1;
k = cFilledPositions.get(l)+1;
try{
isEmpty = checkIfRowIsEmpty(sheet,k,formatter);
if(isEmpty)
{
rowHead = sheet.createRow(k);
}
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e)
{
try{
rowHead = sheet.createRow(k);
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e1){
}
}
}
cFilledPositions.add(k);
}
matched = false;
}
cFilledPositions.clear();
positions.clear();
}