在zipfile.ZipFile中獲得的filename有中日文則很大可能是亂碼,這是因為
在zip標准中,對文件名的 encoding 用的不是 unicode,而可能是各種軟件根據系統的默認字符集來采用(此為猜測),而zipfile中根據文件 flag 檢測的時候,只支持 cp437 和 utf-8。
具體zipfile模塊中的源代碼如下
if flags & 0x800:
# UTF-8 file names extension
filename = filename.decode('utf-8')
else:
# Historical ZIP filename encoding
filename = filename.decode('cp437')
可見編碼被正確識別為utf8時的情況外,都會被識別並decode為cp437編碼,但如果實際是gbk等其他編碼時就變為亂碼了。所以解決的方法在於被decode為cp437后重新再手動轉為正確的編碼。
在實際過程中可以對已經先用zipfile進行解壓,然后對unzip文件夾中的亂碼文件直接進行重命名。具體實現過程如下:
import os
def an_garcode(dir_names):
"""anti garbled code"""
os.chdir(dir_names)
for temp_name in os.listdir('.'):
try:
#使用cp437對文件名進行解碼還原
new_name = temp_name.encode('cp437')
#win下一般使用的是gbk編碼
new_name = new_name.decode("gbk")
#對亂碼的文件名及文件夾名進行重命名
os.rename(temp_name, new_name)
#傳回重新編碼的文件名給原文件名
temp_name = new_name
except:
#如果已被正確識別為utf8編碼時則不需再編碼
pass
if os.path.isdir(temp_name):
#對子文件夾進行遞歸調用
an_garcode(temp_name)
#記得返回上級目錄
os.chdir('..')
an_garcode(os.getcwd())
---------------------
直接上最后成功代碼,使用cp437可以正確讀取部分,但是還有一部分卻打印出來\u的編碼,
因為看了alex的文章,又在catch中加上了utf-8的解碼方式
#-*- coding: utf-8 -*-
import zipfile
# 默認模式r,讀
azip = zipfile.ZipFile("/Users/a/my_file/feise.zip", 'r')
# 返回所有文件夾和文件
zip_list = azip.namelist()
for zip_file in zip_list:
print(zip_file)
print(zip_file.encode('utf-8'))
try:
zip_file = zip_file.encode('cp437').decode('gbk')
except:
zip_file = zip_file.encode('utf-8').decode('utf-8')
print(zip_file)
一句話,就是轉換成unicode,壓縮前是什么編碼,使用什么編碼encode再decode回gbk、utf-8
一句話,就是轉換成unicode,壓縮前是什么編碼,使用什么編碼encode再decode回來
先看測試代碼:
1
2
3
4
5
6
7
8
9
10
|
#-*- coding: utf-8 -*-
import
zipfile
# 默認模式r,讀
azip
=
zipfile.ZipFile(
"/Users/a/my_file/feise.zip"
,
'r'
)
# 返回所有文件夾和文件
zip_list
=
azip.namelist()
for
zip_file
in
zip_list:
print
(zip_file)
print
(zip_file.encode(
'utf-8'
))
|