在python中获取.gz文件的未压缩大小

时间:2009-11-09 22:43:45

标签: python gzip

使用gzip,tell()返回未压缩文件中的偏移量 为了显示进度条,我想知道文件的原始(未压缩)大小 有一个简单的方法可以找到答案吗?

10 个答案:

答案 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

编辑: 正如评论中所建议的那样,第二行中的2io.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)

这是 @noroksolution 的 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)