使用gzip,tell()返回未压缩文件中的偏移量 为了显示进度条,我想知道文件的原始(未压缩)大小 有一个简单的方法可以找到答案吗?
答案 0 :(得分:13)
gzip format指定名为ISIZE
的字段:
这包含原始(未压缩)输入数据模2 ^ 32的大小。
在gzip.py中,我假设您正在使用gzip支持,有一个名为_read_eof
的方法定义如下:
def _read_eof(self):
# We've read to the end of the file, so we have to rewind in order
# to reread the 8 bytes containing the CRC and the file size.
# We check the that the computed CRC and size of the
# uncompressed data matches the stored values. Note that the size
# stored is the true file size mod 2**32.
self.fileobj.seek(-8, 1)
crc32 = read32(self.fileobj)
isize = U32(read32(self.fileobj)) # may exceed 2GB
if U32(crc32) != U32(self.crc):
raise IOError, "CRC check failed"
elif isize != LOWU32(self.size):
raise IOError, "Incorrect length of data produced"
在那里,您可以看到正在读取ISIZE
字段,但只能将其与self.size
进行比较以进行错误检测。这应该意味着GzipFile.size
存储实际的未压缩大小。但是,我认为它没有公开曝光,所以你可能不得不入侵它以暴露它。不太确定,抱歉。
我现在只看了所有这些,我没有尝试过,所以我错了。我希望这对你有用。对不起,如果我误解了你的问题。
答案 1 :(得分:4)
Unix方式:通过subprocess.call / os.popen使用“gunzip -l file.gz”,捕获并解析其输出。
答案 2 :(得分:4)
.gz的最后4个字节保存文件的原始大小
答案 3 :(得分:1)
f = gzip.open(filename)
# kludge - report uncompressed file position so progess bars
# don't go to 400%
f.tell = f.fileobj.tell
答案 4 :(得分:1)
我不确定表现,但这可以通过使用以下方式在不知道gzip
魔法的情况下实现:
with gzip.open(filepath, 'rb') as file_obj:
file_size = file_obj.seek(0, io.SEEK_END)
这也适用于其他(压缩)流阅读器,例如bz2
或普通open
。
编辑:
正如评论中所建议的那样,第二行中的2
被io.SEEK_END
取代,这肯定更具可读性,可能更具前瞻性。
编辑: 仅适用于Python 3。
答案 5 :(得分:1)
尽管有其他答案,但最后四个字节并不是获取gzip文件未压缩长度的可靠方法。首先,gzip文件中可能有多个成员,因此只能是最后一个成员的长度。其次,长度可能大于4 GB,在这种情况下,最后四个字节代表模2 32 的长度。不是长度。
不过,对于您想要的内容,无需获取未压缩的长度。取而代之的是,进度条基于消耗的 input 数量(与容易获得的gzip文件的长度相比)。对于典型的同类数据,进度条将显示与进度条完全相同的内容,而不是基于未压缩的数据。
答案 6 :(得分:0)
查看gzip
模块的源代码,我发现GzipFile
的基础文件对象似乎是fileobj
。所以:
mygzipfile = gzip.GzipFile()
...
mygzipfile.fileobj.tell()
?
在这样做之前做一些健全性检查可能会很好,比如检查属性是否存在hasattr
。
不完全是公共API,但是......
答案 7 :(得分:0)
GzipFile.size存储未压缩的大小,但只有在读取文件时才会增加,所以你应该更喜欢len(fd.read())而不是非公共的GzipFile.size。
答案 8 :(得分:0)
这是 @norok 的 solution 的 Python2 版本
import gzip, io
with oepn("yourfile.gz", "rb") as f:
prev, cur = 0, f.seek(1000000, io.SEEK_CUR)
while prev < cur:
prev, cur = cur, f.seek(1000000, io.SEEK_CUR)
filesize = cur
请注意,就像 f.seek(0, io.SEEK_END)
这对于大文件来说很慢,但它会克服 4GB size limitation 建议的更快解决方案here
答案 9 :(得分:-2)
import gzip
File = gzip.open("input.gz", "r")
Size = gzip.read32(File)