使用
zipfile.is_zipfile('xxx.zip') # 判断文件是否是个有效的zipfile
zipfile.namelist('xxx.zip') # 列表,存储zip文件中所有子文件的path(相对于zip文件包而言的)
zipfile.infolist('xxx.zip') # 列表,存储每个zip文件中子文件的ZipInfo对象
zipfile.printdir() # 打印输出zip文件的目录结构,包括每个文件的path,修改时间和大小
zipfile.open(name[,mode[,pwd]]) # 获取一个子文件的文件对象,可以对其进行read,readline,write等操作
zipfile.setpassword(psw),为zip文件设置默认密码
zipfile.testzip() # 读取zip中的所有文件,验证他们的CRC校验和。返回第一个损坏文件的名称,如果所有文件都是完整的就返回None
zipfile.write(filename[,arcname[,compression_type]]) # 将zip外的文件filename写入到名为arcname的子文件中(当然arcname也是带有相对zip包的路径的),打开方式为w或a
zipfile.extract(member, path=None, pwd=None) # 解压一个zip中的文件,path为解压存储路径,pwd为密码
zipfile.extractall(path[,pwd]) # 解压zip中的所有文件,path为解压存储路径,pwd为密码
中文乱码问题
内置的zipfile模板在解压zip文件的时候,如果其中文件名称存在中文,将会乱码
原因:
在源码中显示zipfile将所有文件名用cp437进行了编码,官方说明
There is no official file name encoding for ZIP files. If you have unicode file names, you must convert them to byte strings in your desired encoding before passing them to write(). WinZip interprets all file names as encoded in CP437, also known as DOS Latin.
解决方案:
先用 CP437 编码 encode 成 bytes,再以 gbk或者utf-8 格式解码成中文 string。
在解压时不用extractall,要用extract对单个文件进行解压
1 对文件流重新写入
import shutil
import zipfile
with zipfile.ZipFile('文件.zip', 'r') as zf:
for fn in zf.namelist():
right_fn = fn.encode('cp437').decode('gbk') # 将文件名正确编码
with open(right_fn, 'wb') as output_file: # 创建并打开新文件
with zf.open(fn, 'r') as origin_file: # 打开原文件
shutil.copyfileobj(origin_file, output_file) # 将原文件内容复制到新文件
2 解压后对文件进行重命名
with zipfile.ZipFile(zipfile_path, 'r') as zip_file:
for file_name in zip_file.namelist():
file_path = Path(zip_file.extract(file_name, dest_path))
print(file_path)
try:
file_name = file_name.encode('cp437').decode('gbk')
except:
file_name = file_name.encode('cp437').decode('utf-8')
file_path.rename(os.path.join(dest_path, file_name))
3 使用os调用终端命令unzip进行解压
-O cp936解除中文乱码,部分机器需要, -o直接覆盖,不展示交互命令
os.popen(f'cd {dest_path} && unzip -O cp936 -o {}')