2016-06-09 55 views
4

問題是,對於一些檔案或文件上傳到python應用程序,ZipFilenamelist()返回嚴重解碼的字符串。ZipFile的namelist()返回一個編碼無效的字符串

from zip import ZipFile 
for name in ZipFile('zipfile.zip').namelist(): 
    print('Listing zip files: %s' % name) 

如何修復該代碼,所以我總是解碼unicode中的文件名(所以支持Chineeze,俄語和其他語言)?

我見過Python 2的一些示例,但由於字符串的本質在python3中發生了變化,我不知道如何重新編碼它,或者對它應用chardet。

+0

HT tp://stackoverflow.com/questions/1807063/extract-files-with-invalid-characters-in-filename-with-python可能會給你一些答案,特別是第二個答案。 – Kush131

回答

4

如何解決該代碼,所以我總是在unicode解碼文件名(所以Chineeze,俄羅斯和其他語言支持)?

自動?你不能。基本ZIP文件中的文件名是字節串,沒有附加的編碼信息,因此除非您知道創建ZIP的計算機上的編碼,否則無法可靠地獲取可讀的文件名。

對現代ZIP文件的標誌有一個擴展名,告訴你文件名是UTF-8。不幸的是,你從Windows用戶那裏收到的文件通常沒有它,所以你會用像chardet這樣固有的不可靠方法進行猜測。

我已經看到了Python 2的一些示例,但由於字符串的本質在python3中發生了變化,我不知道如何對其進行重新編碼或對其應用chardet。

Python 2只會給你原始字節。在Python 3的新特性是:

  • 如果UTF-8標誌設置,它使用UTF-8解碼文件名,你會得到正確的字符串值回

  • 否則,解碼使用DOS代碼頁面437的文件名,這很可能不是預期的。但是,您可以將字符串重新編碼回原始字節,然後嘗試使用您實際需要的代碼頁再次解碼,例如name.encode('cp437').decode('cp1252')

不幸的是(再次,因爲unfortunatelies永遠不會結束,其中ZIP而言),ZipFile默默的做這個解碼不告訴你它的所作所爲。所以,如果你想切換,只有做轉碼的步驟,當文件名是犯罪嫌疑人,你必須複製的邏輯嗅探UTF-8標誌是否被設置:

ZIP_FILENAME_UTF8_FLAG = 0x800 

for info in ZipFile('zipfile.zip').filelist(): 
    filename = info.filename 
    if info.flag_bits & ZIP_FILENAME_UTF8_FLAG == 0: 
     filename_bytes = filename.encode('437') 
     guessed_encoding = chardet.detect(filename_bytes)['encoding'] or 'cp1252' 
     filename = filename_bytes.decode(guessed_encoding, 'replace') 
    ... 
0

這裏的解碼文件名中zipfile.py代碼根據the zip spec that supports only cp437 and utf-8 character encodings

 if flags & 0x800: 
      # UTF-8 file names extension 
      filename = filename.decode('utf-8') 
     else: 
      # Historical ZIP filename encoding 
      filename = filename.decode('cp437') 

正如你所看到的,如果0x800標誌不是IE設置,如果UTF-8是不是在你的輸入使用zipfile.zip然後cp437被使用,因此結果爲「Chineeze,俄羅斯和其他語言「可能是不正確的。

實際上,可以使用ANSI或OEM Windows代碼頁代替cp437。

如果你知道實際的字符編碼如cp866 (OEM (console) codepage) may be used on Russian Windows那麼你可以重新編碼的文件名來獲得原始文件名:

filename = corrupted_filename.encode('cp437').decode('cp866') 

最好的辦法是使用UTF-8,這樣就可以支持創建ZIP檔案在同一歸檔多國語言:

c:\> 7z.exe a -tzip -mcu archive.zip <files>.. 

​​
相關問題