我需要使用gzip
模块压缩文件,但输出文件扩展名可能不是.gz
。
看看这个简单的代码:
import gzip
import shutil
input_path = "test.txt"
output_path = input_path + ".gz"
with open(input_path, 'w') as file:
file.write("abc" * 10)
with gzip.open(output_path, 'wb') as f_out:
with open(input_path, 'rb') as f_in:
shutil.copyfileobj(f_in, f_out)
工作正常。但是,如果我将".gz"
替换为".gzip"
,那么我无法正确打开压缩文件:
我尝试使用7-Zip和WinRar,结果是一样的,即使我重命名该文件,错误仍然存在。
有人知道问题来自哪里吗?
答案 0 :(得分:3)
你实际上有两种版本的文件:
首先,.gz
文件:
with gzip.open("test.txt.gz", 'wb') as f_out:
with open("test.txt", 'rb') as f_in:
shutil.copyfileobj(f_in, f_out)
其次,.gzip
档案:
with gzip.open("test.txt.gzip", 'wb') as f_out:
with open("test.txt", 'rb') as f_in:
shutil.copyfileobj(f_in, f_out)
两者都创建了一个GZIP,其中包含test.txt
。唯一的区别是,在第二种情况下,test.txt
被重命名为test.txt.gzip
。
问题是gzip.open
的参数实际上有两个目的:gzip存档的文件名和文件的内部文件名(bad design,imho)。
因此,如果您执行gzip.open("abcd", 'wb')
并写入,它将创建名为abcd
的gzip存档,其中包含一个名为abcd
的文件。
然而,有魔力:如果文件名以.gz
结尾,那么它的行为会有所不同,例如: gzip.open("bla.gz", 'wb')
创建一个名为bla.gz
的gzip存档,其中包含一个名为bla
的文件。
所以,.gz
你激活了(没有记载,据我所知!)魔法,而.gzip
却没有激活。
答案 1 :(得分:1)
可以通过使用gzip.GzipFile
构造函数而不是gzip.open
方法来控制档案内部的文件名。然后gzip.GzipFile
需要一个单独的os.open
调用。
with open(output_path, 'wb') as f_out_gz:
with gzip.GzipFile(fileobj=f_out_gz, filename=input_path, mode='wb') as f_out:
...
f_out.flush()
还要注意添加的f_out.flush()
-根据我的经验,GzipFile
在某些情况下可能会在关闭文件之前随机不刷新数据,从而导致存档损坏。
或作为完整示例:
import gzip
import shutil
input_path = "test.txt"
output_path = input_path + ".gz"
with open(input_path, 'w') as file:
file.write("abc" * 10)
with open(output_path, 'wb') as f_out_gz:
with gzip.GzipFile(fileobj=f_out_gz, filename=input_path, mode='wb') as f_out
with open(input_path, 'rb') as f_in:
shutil.copyfileobj(f_in, f_out)
f_out.flush()