如何压缩一个大文件?

6
我遇到的问题是存储文件的名称。存储的文件名不是原始/未压缩文件名,而是带有归档名称的文件名(附加了“.gz”扩展名)。
期望结果:
file.txt.gz           {archive name}
....file.txt          {stored file name}

实际结果:

file.txt.gz           {archive name}
....file.txt.gz       {stored file name}

阅读gzip文档 (https://docs.python.org/2.7/library/gzip.html) 的示例代码:

import gzip
import shutil
with open('file.txt', 'rb') as f_in, gzip.open('file.txt.gz', 'wb') as f_out:
    shutil.copyfileobj(f_in, f_out)

如何使归档工具存储名为“file.txt”而不是“file.txt.gz”的文件?


您想把压缩文件存储在 file.txt 中吗?即覆盖现有文件? - oxalorg
2
但是现在我看看周围,不认为gzip是一个实际的存档格式,只是文件压缩 -_- - Wayne Werner
1
还有一个想法:我尝试了这段代码,它可以正常工作,文件名正确地存储在归档中(“file.txt”)。 - brezniczky
1
@Jake,更好的了解实际使用的Python版本以及如何解压文件会很有帮助,因为我的版本与引用文档链接相对应,所以如果存在问题,这不太可能是特定于2.7的问题(但我们没有太多线索)。 - brezniczky
1
是的,这不是 gzip 模块应该工作的方式。你要么发现了一个旧 bug,要么存在误解,或者你的代码里出现了一些有趣的问题。 - André Laszlo
显示剩余3条评论
2个回答

6
您需要使用gzip.GzipFile(),简写的gzip.open()无法实现您想要的功能。
引用文档中的话:
fileobj不为None时,filename参数仅用于包含在gzip文件头中,其中可能包括未压缩文件的原始文件名。如果可以辨认出,则默认为fileobj的文件名;否则,默认为空字符串,在这种情况下,原始文件名不包括在头中。
请尝试以下操作:
import gzip
import shutil
with open('file.txt', 'rb') as f_in:
    with open('file.txt.gz', 'wb') as f_out:
        with gzip.GzipFile('file.txt', 'wb', fileobj=f_out) as f_out:
            shutil.copyfileobj(f_in, f_out)

-1

你在区分“存储文件名”和“归档名称”,但对于gzip压缩来说,这是错误的思考方式,因为gzip不是一种归档格式,而只是一种压缩协议。

当你存储一个'gzip'文件时,它并不(必须)记住原始文件名。只有原始文件的压缩内容,你可以给它任何你想要的名称。有一个约定,将其命名为与原始文件相同的名称,但附加了“.gz”。Unix系统上的“gzip”和“gunzip”实用程序会在你仅提供文件名时假定这一点:

gzip foo.txt
# now foo.txt has been deleted, and foo.txt.gz exists
gunzip foo.txt.gz
# now you have foo.txt back, and foo.txt.gz has been deleted.

如果你将foo.txt.gz重命名为bar.txt.gz,然后使用Unix gunzip解压缩,你会得到'goo.txt'(但其他实用程序可能会执行不同的操作)。

但是,您可以在流模式下使用gzip和gunzip,在这种情况下,它们对文件名一无所知 - gzip实际上是关于压缩的,不关心文件名。

(编辑:gzip可以存储文件名,但在某些情况下可能无法存储(如果没有原始“文件”,只有数据),以及在解压缩时是否使用此选项完全是可选的)。


1
我认为那是不正确的。文件名很可能存储在维基百科提到的gzip文件头中。尝试实际重命名一个gzip文件,然后解压缩它 - 你会得到之前的原始文件名。或者至少我用安装的软件得到了它。 - brezniczky
@brezniczky 是正确的,但有一个修改,"未压缩的名称"是从使用 gzip.open 的文件名派生出来的。如果你打开文件 foo.txt.gz,则头部中的未压缩名称将是 foo.txt,即使源文件可能被称为 bar.txt。请参见gzip模块源代码以获取逻辑。 - André Laszlo
你说得对,我没有意识到gzip实际上会存储原始文件名。Unix的gunzip在解压缩时不使用它,除非你传递“-N”,这不是默认设置,因此不能依赖它。Python模块可能会做其他事情,但通常应将gzip视为数据压缩格式,而不是归档格式。 - spookylukey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接