python zip 檔案解壓中文亂碼問題解決
阿新 • • 發佈:2019-01-01
今天突然碰到zip檔案解壓後中文亂碼問題。百度了下覺得這篇文章不錯。儲存儲存。
來源:http://blog.sina.com.cn/s/blog_5805e98101012uzv.html
萬惡的編碼!!!!!!!!!!
學習 python 2.x 時就被時不時出現的中文亂碼問題搞得頭大,無奈用起來資料挺少、支援不多的 python 3.x,沒想到昨天來解壓縮一大堆檔案時仍然遇到亂碼的問題,對 python 3.x 失望之極。不得已,又拿起C#來解決。其實在C#中也有亂碼的問題,最終是用 FileStream 變相解決的。
所以其實最初可能冤枉了 python 3.x 了,自它採用 unicode 之後,亂碼問題其實少多了,有的時候還是不熟練。
今天又硬著頭皮看 ZipFile 的原始碼,在一堆英文資料中翻來翻去。其實這一 bug 已經早被提出來了,只是沒有解決,可能是負責解決問題的大牛們都不用中文系統,尤其是都不用中文Windows系統,所以官方居然說已經修復了。
下面說一下原因及解決辦法。
在zip標準中,對檔名的 encoding 用的不是 unicode,而可能是各種軟體根據系統的預設字符集來採用(此為猜測),因此zipfile中根據檔案 flag 檢測的時候,只支援 cp437 和 utf-8。具體就是查詢 zipfile.py 原始碼找到下面的程式碼:
1: if flags & 0x800:
2: # UTF-8 file names extension
3: filename = filename.decode('utf-8')
4: else:
5: # Historical ZIP filename encoding
6: filename = filename.decode('cp437')
修改如下:
1: if sys.getfilesystemencoding()=='mbcs':
2: filename=filename.decode('mbcs')
3: elif flags & 0x800:
4: # UTF-8 file names extension
5: filename = filename.decode('utf-8')
6: else:
7: # Historical ZIP filename encoding
8: filename = filename.decode('cp437')
後面一處同樣如此修改:
1: if sys.getfilesystemencoding()=='mbcs':
2: fname_str = fname.decode('mbcs')
3: elif zinfo.flag_bits & 0x800:
4: # UTF-8 filename
5: fname_str = fname.decode("utf-8")
6: else:
7: fname_str = fname.decode("cp437")
當然這種辦法只是暫時性的解決了這一問題,可能在其它系統中採用會帶來更多的問題。