Python zipfile模块无法提取带有中文字符

时间:2016-12-07 14:11:36

标签: python-2.7 unicode zipfile

我正在尝试使用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”完美地访问/解压缩同一个文件。

4 个答案:

答案 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(); 
        }
相关问题