参考:python 之路,致那些年,我们依然没搞明白的编码 https://www.cnblogs.com/alex3714/articles/7550940.html
Python中的zipfile模块用来解压缩ZIP文件非常方便,但是如果ZIP文件的子文件的文件名里含有中文的话,解压出出来的文件的文件名却是乱码!这到底是为什么呢?
查看zipfile的源码后,终于找到原因: if zinfo.flag_bits & 0x800: # UTF-8 filename fname_str = fname.decode("utf-8") else: fname_str = fname.decode("cp437") 原来编码不能被正确识别为utf-8的时候,会被是被识别并decode为cp437编码,如果原来是gbk编码的话就会变成乱码。 知道是什么原因后,解决的办法也很简单,那就是将文件名先使用cp437编码encode,然后再用gbk编码decode即可,来试试吧! import os import zipfile is_zip = zipfile.is_zipfile(filePath) if is_zip: zip_file_contents = zipfile.ZipFile(filePath, 'r') for file in zip_file_contents.namelist(): filename = file.encode('cp437').decode('gbk')#先使用cp437编码,然后再使用gbk解码 print(filename) zip_file_contents.extract(file,release_file_dir)#解压缩ZIP文件 os.chdir(release_file_dir)#切换到目标目录 os.rename(file,filename)#重命名文件
中文在编程中各种坑爹,python3下中文乱码这个问题令人头疼。看了alex的文章,才有种恍然大悟的感觉。 一句话,就是转换成unicode,压缩前是什么编码,使用什么编码encode再decode回来 先看测试代码: # -*- coding: utf-8 -*- import zipfile # 默认模式r,读 zip_file = zipfile.ZipFile("/Users/feise.zip", 'r') # 返回所有文件夹和文件 zip_list = zip_file.namelist() for file in zip_list: print(file) print(file.encode('utf-8')) 真实文件名 绯色 / w1985jc / 沈嫣日记 / 8 _【沈嫣日记】(33 - 完).txt print(file): τ│╔½ / ú≈ú▒ú╣ú╕ú╡úΩúπ /╔≥µ╠╚╒╝╟ / 8 _í╛╔≥µ╠╚╒╝╟í┐ú¿33 -═Ωú⌐.txt print(file.encode('utf-8')): b'\xcf\x84\xe2\x94\x82\xe2\x95\x94\xc2\xbd/\xc3\xba\xe2\x89\x88\xc3\xba\xe2\x96\x92\xc3\xba\xe2\x95\xa3\xc3\xba\xe2\x95\x95\xc3\xba\xe2\x95\xa1\xc3\xba\xce\xa9\xc3\xba\xcf\x80/\xe2\x95\x94\xe2\x89\xa5\xc2\xb5\xe2\x95\xa0\xe2\x95\x9a\xe2\x95\x92\xe2\x95\x9d\xe2\x95\x9f/8_\xc3\xad\xe2\x95\x9b\xe2\x95\x94\xe2\x89\xa5\xc2\xb5\xe2\x95\xa0\xe2\x95\x9a\xe2\x95\x92\xe2\x95\x9d\xe2\x95\x9f\xc3\xad\xe2\x94\x90\xc3\xba\xc2\xbf33-\xe2\x95\x90\xce\xa9\xc3\xba\xe2\x8c\x90.txt' 成功代码,使用cp437可以正确读取部分,但是还有一部分却打印出来\u的编码,因为看了alex的文章,又在catch中加上了utf8的解码方式 # -*- coding: utf-8 -*- import zipfile # 默认模式r,读 zip_file = zipfile.ZipFile("/Users/feise.zip", 'r') # 返回所有文件夹和文件 zip_list = zip_file.namelist() for file in zip_list: print(file) print(file.encode('utf-8')) try: file = file.encode('cp437').decode('gbk') except: file = file.encode('utf-8').decode('utf-8') print(file) 一句话,就是转换成unicode,压缩前是什么编码,使用什么编码encode再decode回gbk、utf8
具体实现过程如下:
import os def anti_garbled_code(dir_names): 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): # 对子文件夹进行递归调用 anti_garbled_code(temp_name) # 记得返回上级目录 os.chdir('..') anti_garbled_code(os.getcwd())