解壓縮zip文件
import zipfile import os.path import os class ZFile(object): """ 文件壓縮 """ def zip_file(self, fs_name, fz_name): """ 從壓縮文件 :param fs_name: 源文件名 :param fz_name: 壓縮后文件名 :return: """ flag = False if fs_name and fz_name: try: with zipfile.ZipFile(fz_name, mode='w', compression=zipfile.ZIP_DEFLATED) as zipf: zipf.write(fs_name) print( "%s is running [%s] " % (currentThread().getName(), fs_name)) print('壓縮文件[{}]成功'.format(fs_name)) if zipfile.is_zipfile(fz_name): os.remove(fs_name) print('刪除文件[{}]成功'.format(fs_name)) flag = True except Exception as e: print('壓縮文件[{}]失敗'.format(fs_name), str(e)) else: print('文件名不能為空') return {'file_name': fs_name, 'flag': flag} def unzip_file(self, fz_name, path): """ 解壓縮文件 :param fz_name: zip文件 :param path: 解壓縮路徑 :return: """ flag = False if zipfile.is_zipfile(fz_name): # 檢查是否為zip文件 with zipfile.ZipFile(fz_name, 'r') as zipf: zipf.extractall(path) # for p in zipf.namelist(): # # 使用cp437對文件名進行解碼還原, win下一般使用的是gbk編碼 # p = p.encode('cp437').decode('gbk') # 解決中文亂碼 # print(fz_name, p,path) flag = True return {'file_name': fz_name, 'flag': flag}
解決中文亂碼問題:
在zip標准中,對文件名的 encoding 用的不是 unicode,而可能是各種軟件根據系統的默認字符集來采用(此為猜測),因此zipfile中根據文件 flag 檢測的時候,只支持 cp437 和 utf-8。具體就是查找 zipfile.py 源代碼找到下面的代碼:
找到python3 的安裝目錄, 搜索 zipfile.py這個文件,改兩個地方
可見編碼被正確識別為utf8時的情況外,都會被識別並decode為cp437編碼,但如果實際是gbk等其他編碼時就變為亂碼了
第一.
if zinfo.flag_bits & 0x800: # UTF-8 filename fname_str = fname.decode("utf-8") else: # fname_str = fname.decode("cp437") fname_str = fname.decode("gbk") # 這句是我添加的 解決win下中文亂碼
第二..
if flags & 0x800: # UTF-8 file names extension filename = filename.decode('utf-8') else: # Historical ZIP filename encoding # filename = filename.decode('cp437') filename = filename.decode("gbk") # 這句是我添加的,解決win下中文亂碼問題
