目录
Gzip是若干种文件压缩程序的简称,通常指GNU计划的实现,此处的gzip代表GNU zip。也经常用来表示gzip这种文件格式。
GZIP最早由Jean-loup Gailly和Mark Adler创建,用于UNⅨ系统的文件压缩。我们在Linux中经常会用到后缀为.gz的文件,它们就是GZIP格式的。现今已经成为Internet 上使用非常普遍的一种数据压缩格式,或者说一种文件格式。
HTTP协议的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。这一般是指WWW服务器中安装的一个功能,当有人来访问这个服务器中的网站时,服务器中的这个功能就将网页内容压缩后传输到来访的电脑浏览器中显示出来.一般对纯文本内容可压缩到原大小的40%.这样传输就快了,效果就是你点击网址后会很快的显示出来.当然这也会增加服务器的负载. 一般服务器中都安装有这个功能模块的。
gzip的基础是DEFLATE,DEFLATE是LZ77与哈夫曼编码的一个组合体。尽管这种文件格式允许多个这样的数据拼接在一起,在解压时也能认出它们是拼接在一起的数据,但通常gzip仅用来压缩单个文件。多个文件的压缩归档通常是首先将这些文件合并成一个tar文件,然后再使用gzip进行压缩,最后生成的.tar.gz或者.tgz文件就是所谓的“tar压缩包”或者“tarball”。
注意不要将gzip和ZIP压缩格式混淆。ZIP也使用DEFLATE算法,而且可移植性更好,不需要一个外部的归档工具就可以包容多个文件。但是,由于ZIP对每个文件进行单独压缩而没有利用文件间的冗余信息(即固实压缩),所以ZIP的压缩率会稍逊于tar压缩包。
gzip库是python的标准库,此模块提供的简单接口帮助用户压缩和解压缩文件,功能类似于 GNU 应用程序 gzip 和 gunzip。数据压缩由 zlib
模块提供。
gzip模块提供 GzipFile
类和 open()
、compress()
、decompress()
几个便利的函数。GzipFile
类可以读写 gzip 格式的文件,还能自动压缩和解压缩数据,这让操作压缩文件如同操作普通的 file object 一样方便。
注意,此模块不支持部分可以被 gzip 和 gunzip 解压的格式,如利用 compress 或 pack 压缩所得的文件。
- gzip.open(
- filename,
- mode='rb',
- compresslevel=9,
- encoding=None,
- errors=None,
- newline=None)
以二进制方式或者文本方式打开一个 gzip 格式的压缩文件,返回一个 file object。
参数说明:
filename:参数可以是一个实际的文件名(一个str 对象或者bytes对象), 或者是一个用来读写的已存在的文件对象。
mode:参数可以是二进制模式'r'
, 'rb'
, 'a'
, 'ab'
, 'w'
, 'wb'
, 'x'
or 'xb'
, 或者是文本模式 'rt'
, 'at'
, 'wt'
, or 'xt'
。默认值是 'rb'
。它的默认值是'r',表示以文本模式打开阅读。其他常见的值有:'w'用于写入(如果文件已经存在,则截断它),'x'用于独占创建,'a'用于追加(在一些Unix系统上,这意味着所有的写入都追加到文件的末尾,不管当前的寻址位置如何)。在文本模式下,如果没有指定编码,使用的编码是与平台有关的:调用locale.getpreferredencoding(False)来获得当前的locale编码。(对于读写原始字节,使用二进制模式,不指定编码。) 可用的模式。
compresslevel参数是从0到9的整数,压缩等级; 压缩格式分类。
- import gzip
-
- # 创建一个gzip文件
- content = "Hello world!"
- f = gzip.open('file.txt.gz', 'wb')
- f.write(content.encode())
- f.close()
其中'wb'就是写入,若没有该路径文件将会自动生成一个文件。
- class gzip.GzipFile(
- filename=None,
- mode=None,
- compresslevel=9,
- fileobj=None,
- mtime=None)
GzipFile
类的构造器支持 truncate()
的异常,与 file object 的大多数方法非常相似。fileobj和 filename至少有一个不为空。
新的实例基于 fileobj,它可以是一个普通文件,一个 io.BytesIO
对象,或者任何一个与文件相似的对象。当 filename 是一个文件对象时,它的默认值是 None
。
当 fileobj 为 None
时, filename 参数只用于 gzip 文件头中,这个文件有可能包含未压缩文件的源文件名。如果文件可以被识别,默认 fileobj 的文件名;否则默认为空字符串,在这种情况下文件头将不包含源文件名。
需要注意的是,文件默认使用二进制模式打开。如果要以文本模式打开文件一个压缩文件,应该使用 open()
方法(或者使用 io.TextIOWrapper
包装 GzipFile
)。
调用 GzipFile
的 close()
方法不会关闭 fileobj,可以将一个 io.BytesIO
对象作为 fileobj,也可以使用 io.BytesIO
的 getvalue()
方法从内存缓存中恢复数据。
GzipFile
支持 io.BufferedIOBase
类的接口, 包括迭代和 with
语句。只有 truncate()
方法没有实现。
- import gzip
- # 创建GzipFile实例
- zf = gzip.GzipFile('file_1.txt.gz', mode = 'wb')
- contents = "Hello world!Friend!"
- zf.write(contents.encode()) # 写文件
- zf.close() # 关闭
另外一种方法是用gzip.comress()方法将从文件中读出的数据进行压缩,再将压缩后的数据写入到文件中。
- import gzip
-
- contents = "Hello world!Friend!"
- pf = gzip.open('file_2.txt.gz', 'wb')
- data_comp = gzip.compress(contents.encode()) # 压缩数据
- pf.write(data_comp) # 写文件
- pf.close() # 关闭
从压缩文件看该方法和前2种效果是一样的。
下面这种方法更简便、更安全:
- import gzip
- with open('file_3.txt.gz', 'wb') as pw, open('file_3.txt','rb') as pr:
- pw.write(gzip.compress(pr.read()) )
直接open就可以了:
- import gzip
- zip_filename = 'file.txt.gz'
- with open('./file_1.txt','wb') as pw:
- zf = gzip.open(zip_filename, mode = 'rb')
- pw.write(zf.read()) # 写文件
- zf.close()
和压缩方法的顺序是一样的,使用GzipFile就好了:
- zip_filename = 'file_2.txt.gz'
- with open('./file_2.txt','wb') as pw:
- zf = gzip.GzipFile(zip_filename, mode = 'rb')
- pw.write(zf.read()) # 写文件
- zf.close()
- zip_filename = 'file_3.txt.gz'
- with open(zip_filename, 'rb') as pr, open('./file_3.txt','wb') as pw:
- pw.write(gzip.decompress(pr.read()) )
- import os
- import gzip
-
-
- def unzip_gz_file(path, new_path):
- count = 0
- try:
- for f_path in os.listdir(path):
- if '.gz' in f_path:
- try:
- with gzip.GzipFile(fileobj=open(path + "/" + f_path, 'rb'), mode='rb') as g:
- with open(new_path + "/" + f_path.replace(".gz", ""), "wb") as f:
- f.write(g.read())
- print(count, f"文件{f_path} 解压完成...")
- except Exception as e:
- print(f_path, e)
- count += 1
- except Exception as e:
- print(e)
- else:
- print("文件全部解压完成!")
-
-
- path = './'
- new_path = './unzip_file'
- unzip_gz_file(path, new_path)
以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见。