(译)Python zipfile模块介绍
Jan 20, 2014
本文内容适用于 python 2.x 版本
原文链接:zipfile — Work with ZIP archives。翻译过程中结合了自己的理解,并给出了一些示例代码。
zip是一种常见的压缩格式,Python中提供了zipfile模块来支持zip格式压缩文件的操作,包括文件压缩、解压缩、查看压缩文件信息等,还支持加密文件的解密(不过解密速度慢,因为是使用Python完成,而非C语言),zipfile目前不支持文件的加密。通过设置zipfile.ZipFile()函数的allowZip64参数为True,可以支持大小超过4G的zip文件的操作。
zipfile模块包含的内容主要如下:
exception zipfile.BadZipfile
:当zip文件破损时抛出的异常exception zipfile.LargeZipfile
:当文件过大,而且allowZip64也没有设置为True时,抛出此异常class zifile.ZipFile
:处理zip文件的类。用来打开、读写zip文件class zipfile.ZipInfo([filename[, date_time]])
:代表压缩文件中的一个被压缩的文件的类。ZipFile类的getinfo()和infolist()函数返回的是ZipInfo类的对象实例。通常,ZipInfo类的具体对象不需要我们创建,而是由函数返回得到。filename是zip文件的包含路径的完整文件名,date_time是一个包含了文件最新修改时间的有6个元素“年-月-日-时-分-秒”的元组(tuple),如(1999, 9, 11, 20, 11, 8)。zipfile.is_zipfile(filename)
:基于文件的幻数(magic number,用来标记文件的格式,如rar格式文件的开头为Rar,zip文件开头为PK)判断文件filename是否是有效的zip文件,是则返回True,否则返回False。zipfile.ZIP_STORED
:代表未解压的压缩文件中的文件的数字常量。(The numeric constant for an uncompressed archive member.)zipfile.ZIP_DEFLATED
:代表通常压缩方法的数字常量。这个需要zlib模块的支持。目前还不支持其它的压缩方法。【deflate是一个压缩算法。它是无损压缩】
ZipFile类 #
ZipFile类用来处理zip文件,提供打开、解压缩等。ZipFile类的主要内容有:
class zipfile.ZipFile(file [,mode [,compression [,allowZip64] ] ])
ZipFile类构造函数,打开一个zip文件,并返回该zip文件的ZipFile对象。
file
:要打开的zip文件的文件名,可以是一个普通的文件名(一个string),或者是一个类文件(file-like)的对象。mode
:文件打开方式。‘r’表示读取已存在的文件,‘w’表示截取(即存在则清空)并写一个新文件, ‘a’表示追加到一个已存在的文件后面(如果file指向的不是一个zip文件,那么将会创建一个新的zip文件,并且附加到file指向的文件,示例如下)。
#coding=utf-8
#author=JarvisChu
import zipfile
#创建zip文件,使用'a'追加模式,同时file指向一个已存在的非zip文件
zf = zipfile.ZipFile('flower.jpg','a',zipfile.ZIP_DEFLATED)
#创建一个文本文件 1.txt
f = open('1.txt','w')
f.write('This a simple text file')
f.close()
#将文本文件附加到flower中
zf.write('1.txt')
#关闭zip文件
zf.close()
使用 ‘a’ 模式打开了一张jpg图片,然后创建了一个1.txt文本文件并写入到压缩文件。运行上述脚本,则将包含1.txt的压缩文件附加到了flower.jpg图片文件中。此时,磁盘中直接打开flower.jpg则显示图片,如果改后缀名jpg为zip,则变为一个zip文件,打开后为包含了1.txt的压缩文件。
这就是图片种子
,原理就是将一个zip压缩文件附加到,或称为隐藏到一个图片文件中。在Windows系统中,可以另一种简单的制作方法:比如要将b.zip文件隐藏到a.jpg图片中,得到的图片种子命名为c.jpg,则打开cmd,切换到文件所在目录,输入下面一行命令即可
copy a.jpg /B + b.zip = c.jpg
c.jpg显示为a.jpg的图片,如果改后缀为zip,则变成了显示b.zip压缩文件。继续回到正文:
- compression:当网往zip文件中写时使用的压缩算法,必须是ZIP_STORED或者ZIP_DEFLATED。如果该参数不是这两个可选值,则抛出RuntimeError异常。如果只为ZIP_DEFLATED,但是zlib模块不可用,则仍抛出RuntimeError异常。默认值为ZIP_STORED。如果allowZip64设为True,则当zip文件大于2GB时,会使用ZIP64扩展来创建zip文件。如果值为False(默认),当文件需要ZIP64扩展时,则会抛出异常。ZIP64扩展默认设置为无效,是因为Unix系统上zip和unzip命名不支持该扩展。
ZipFile.close() #
关闭zip压缩文件。在程序退出时,必须调用close函数,否则一些必须的记录不会被写到文件中。
ZipFile.getinfo(name) #
返回压缩文件中名为name的文件的ZipInfo对象。如果name文件不存在,则抛出KeyError异常
ZipFile.infolist() #
返回一个包含了压缩文件中所有文件各自对应的ZipInfo对象的列表。列表中的排列顺序和在实际压缩文件中的排列顺序相同。
ZipFile.namelist() #
返回一个包含了压缩文件中所有文件的名字的列表。
ZipFile.open(name [,mode [,pwd ] ]) #
解压压缩文件中一个文件得到类文件(file-like)对象。
- name:压缩文件中的一个文件名或者是一个ZipInfo对象。
- mode:必须是’r’、‘U’或者’rU’。默认为’r’。选择’U’或者’rU’会使得只读对象中的universal newline功能生效。
- pwd:解压密码。对一个关闭的ZipFile调用open()会抛出RuntimeError异常。
注1:file-like对象是只读的,且提供了如下函数:read()、readline()、readlines()、iter()、next()
注2:open()、read()和extract()函数,都接受一个文件名或者一个ZipInfo对象。当zip文件中存在重名的文件时,你会喜欢用这个方法的。
ZipFile.extract(member [,path [,pwd]]) #
解压zip文件中的文件member到当前工作目录。文件的信息会尽可能准确的被解压出来。path指示解压到另一个目录。pwd是解压密码。
ZipFile.extractall([path [,members [,pwd]]]) #
解压所有文件到当前工作目录。path指示解压到另一个目录。pwd是解压密码。
#coding=utf-8
import zipfile
zf = zipfile.ZipFile('simple.zip','r',zipfile.ZIP_DEFLATED)#打开已存在的zip文件
zf.extractall()#解压到当前目录
#zf.extractall('..') #解压到上一级目录
#zf.extractall('C:/tmp')#解压到C:/tmp文件夹,文件夹不存在则创建
zf.close()[/python]
ZipFile.printdir()
以表格形式显示压缩文件中所有文件。
import zipfile
zf = zipfile.ZipFile('test.zip','r',zipfile.ZIP_DEFLATED)
zf.printdir()
zf.close()
结果如下dir1为文件夹:
File Name Modified Size
1.txt 2014-01-20 19:04:32 23
2.txt 2014-01-20 19:04:32 23
dir1/ 2014-01-20 19:06:50 0
dir1/11.txt 2014-01-20 19:06:26 0
dir1/12.txt 2014-01-20 19:06:26 0
ZipFile.setpassword(pwd) #
设置pwd为默认解压密码,用来解压加密的文件。
ZipFile.read(name [,pwd]) #
返回压缩文件中name文件的字节(bytes)。压缩文件必须是以read或者append模式打开。
- name:文件名或ZipInfo对象
- pwd:解压密码。如果指定了该参数,会覆盖sefpassword()中指定的默认解码密码。
对已经关闭的zip文件调用read()会产生一个RuntimeError的异常。
# -*- coding: utf-8 -*-
import zipfile
#———————————————-
# 解压文件示例
#打开压缩包
zf = zipfile.ZipFile('simple.zip','r') #读取压缩包中的文件信息
for info in zf.infolist():
print info.filename,info.date_time,info.file_size
#输出: 1.txt (2014, 1, 2, 13, 16, 26) 23
#解压文件
for name in zf.namelist(): #文件名列表
#print name #1.txt,2.txt…
f = file(name,'w')
f.write(zf.read(name)) #read函数读取文件内容
f.close()
#关闭压缩包
zf.close()
simple.zip中包含了1.txt,2.txt,3.txt,4.txt四个文件。zf.namelist()返回压缩文件中所有文件名列表。使用zf.read(name)读取文件中的所有字节,然后写入另一个文件则实现了解压。
ZipFile.testzip() #
读取压缩包中所有文件,并检查它们的CRC和文件头。返回第一个破损的文件的名字,或者None。对已关闭的ZipFile对象调用testzip()会抛出RuntimeError异常。
ZipFile.write(filename [,arcname [,compress_type]]]) #
将文件名为filename的文件写入到压缩文件中。arcname指示在压缩包中文件重命名的名字,不指定则和原文件名相同。compress_type指示压缩类型,如果指定了该参数则会覆盖创建时的compression参数。压缩文件必须以write或append模式打开,否则抛出RuntimeError异常。对已关闭的ZipFile调用该函数也会抛出RuntimeError异常。
注意:官方没有规定的文件名的编码。如果你有一个unicode类型(相对str类型而言的)的文件名,你必须先转换成字节字符串(byte strings,即str类型的有编码的字符串),然后再传递给write()
# -*- coding: utf-8 -*-
import zipfile
#———————————————-
# 压缩文件示例
txt = "This a simple text file"
#创建一个压缩文件
zf = zipfile.ZipFile('simple.zip','w',zipfile.ZIP_DEFLATED)
#创建4个txt文件,(1.txt,2.txt…),并添加到压缩文件
for i in range(1,5):
filename = str(i)+".txt"
f = file(filename,'w')
f.write(txt)
f.close()
#添加到压缩文件
zf.write(filename)
#关闭压缩文件
zf.close()
ZipFile.writestr(zinfo_or_arcname,bytes [,compress_type]) #
将字节串bytes写入到压缩包中。zinfo_or_arcname是压缩包中给定的文件名或者一个ZipInfo实例。如果是ZipInfo实例,至少要给出文件名、日期date和时间time。如果是文件名,date和time会被设置为当前的日期和时间。
注意:当将一个ZipInfo实例作为参数传入时,压缩函数使用ZipInfo实例中指定的compress_type。默认时,ZipInfo构造函数将这个参数设置w为ZIP_STORED.
ZipFile.debug #
ZipFile类的数据成员。指示debug输出时使用的等级。可以设置为0-3。0为默认,表示无输出,3表示the most output。
ZipFile.comment #
ZipFile类的数据成员。zip文件的注释信息。如果给使用’a’或’w’模式创建的ZipFile实例添加了注释,这个注释不能超过65535字节。超过这一大小的会被截断。【一个使用了comment的示例:PythonChallenge系列-P6 ZipFile】
PyZipFile类 #
PyZipFile的构造函数的参数与ZIpFile构造函数参数相同。PyZipFile类的实例比ZipFile对象实例多一个方法。
PyZipFile.writepy(pathname [,basename]) #
查找*.py文件并将其相关文件添加到压缩包中。如果存在*.pyo文件,则相关文件为*.pyo,否则为一个*.pyc文件,如果需要的话会编译该文件。如果pathname是一个以.py结尾的文件,则将相关文件(.pyo 或.pyc)添加到压缩包的最顶层,如果不是则抛出RuntimeError异常。如果pythname是一个目录,那么该目录下所有的pyc和pyo会被添加到压缩包最顶层,如果目录下有子目录,则递归添加。basename只用于内部使用。writepy()函数创建的文件名如下:
string.pyc # Top level name
test/__init__.pyc # Package directory
test/test_support.pyc # Module test.test_support
test/bogus/__init__.pyc # Subpackage directory
test/bogus/myfile.pyc # Submodule test.bogus.myfile
ZipInfo类 #
ZipInfo类的实例由ZipFile对象的getinfo()和infolist()函数返回。每一个对象值保存压缩包中一个文件的信息。ZipInfo对象有如下属性:
ZipInfo.filename #
压缩包中的该文件名
ZipInfo.date_time #
压缩包中该文件的最新修改时间,是一个包含6个元素的元组tuple。
Index Value
0 Year (>=1980)
1 Month (one-based)
2 Day of Month (one-based)
3 Hours (zero-based)
4 Minutes (zero-based)
5 Seconds (zero-based)
注意:不支持早于1980年的时间。
ZipInfo.compress_type #
文件的压缩类型
ZipInfo.comment #
文件的注释
ZipInfo.extra #
附加数据。PKZIP Application Note给出了这个字符串中包含的结构体的一些注解。
ZipInfo.create_system #
创建zip文件的系统
ZipInfo.create_version #
创建zip文件的PKZIP版本
ZipInfo.extract_version #
解压压缩包需要的PKZIP版本号
ZipInfo.reserved #
必须是0
ZipInfo.bits #
zip文件的标识位
ZipInfo.volume #
文件头的卷号(volume number)
ZipInfo.internal_attr #
文件的内部属性
ZipInfo.external_attr #
文件的外部属性
ZipInfo.header_offset #
文件头部的偏移字节数
ZipInfo.CRC #
未压缩的文件的CRC-32
ZipInfo.compress_size #
压缩数据的大小
ZipInfo.file_size #
未压缩的文件的大小