Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
获取python中.gz文件的未压缩大小_Python_Gzip - Fatal编程技术网

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

获取python中.gz文件的未压缩大小,python,gzip,Python,Gzip,使用gzip,tell()返回未压缩文件中的偏移量。 为了显示进度条,我想知道文件的原始(未压缩)大小。 有没有一个简单的方法可以找到 Unix方式:通过subprocess.call/os.popen使用“gunzip-l file.gz”,捕获并解析其输出。查看gzip模块的源代码,我发现GzipFile的底层文件对象似乎是fileobj。因此: mygzipfile = gzip.GzipFile() ... mygzipfile.fileobj.tell() ? 在执行此操作之前,可能

使用gzip,tell()返回未压缩文件中的偏移量。
为了显示进度条,我想知道文件的原始(未压缩)大小。

有没有一个简单的方法可以找到

Unix方式:通过subprocess.call/os.popen使用“gunzip-l file.gz”,捕获并解析其输出。

查看
gzip
模块的源代码,我发现
GzipFile
的底层文件对象似乎是
fileobj
。因此:

mygzipfile = gzip.GzipFile()
...
mygzipfile.fileobj.tell()
?

在执行此操作之前,可能最好先执行一些健全性检查,例如检查属性是否存在于
hasattr


不完全是公共API,但…

的最后4个字节保存文件的原始大小

指定一个名为
ISIZE
的字段,该字段:

它包含原始(未压缩)输入数据的大小,模为2^32

在中,我假设您使用的是gzip支持,有一个名为
\u read\u 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
进行比较以进行错误检测。这意味着
gzip文件.size
存储实际的未压缩大小。然而,我认为它并没有公开,所以你可能不得不破解它来公开它。不太确定,对不起


我现在只是查了一下,但我没有试过,所以我可能是错的。我希望这对你有用。抱歉,如果我误解了您的问题。

GzipFile.size存储未压缩的大小,但它仅在读取文件时递增,因此您应该选择len(fd.read())而不是非公共的GzipFile.size。

未压缩的大小存储在gzip文件的最后4个字节中。我们可以读取二进制数据并将其转换为整数(这仅适用于4GB以下的文件)

    f = gzip.open(filename)
    # kludge - report uncompressed file position so progess bars
    # don't go to 400%
    f.tell = f.fileobj.tell

我不确定性能,但这可以在不知道
gzip
magic的情况下通过以下方法实现:

with gzip.open(filepath, 'rb') as file_obj:
    file_size = file_obj.seek(0, io.SEEK_END)
这也适用于其他(压缩)流读取器,如
bz2
或普通
open

编辑: 正如评论中所建议的那样,第二行中的
2
io.SEEK\u END
所取代,这无疑更具可读性,并且可能更具未来证明

编辑:
仅适用于Python 3。

不管其他答案怎么说,最后四个字节不是获取gzip文件未压缩长度的可靠方法。首先,gzip文件中可能有多个成员,因此这将只是最后一个成员的长度。其次,长度可能超过4GB,在这种情况下,最后四个字节表示长度模232。不是长度


但是,对于您想要的内容,不需要获取未压缩的长度。相反,您可以将进度条基于消耗的输入量,而不是容易获得的gzip文件的长度。对于典型的同质数据,该进度条将显示与基于未压缩数据的进度条完全相同的内容。

这里是针对的Python2版本

导入gzip,io
将oepn(“yourfile.gz”、“rb”)作为f:
上一个,当前=0,f.seek(1000000,io.seek\u cur)
当上一个<当前:
上一个,当前=当前,f.seek(1000000,io.seek\u cur)
filesize=cur

请注意,就像
f.seek(0,io.seek_END)
一样,这对于大文件来说很慢,但它将克服建议的更快解决方案的缺点

永远不要接触比我旧的操作系统。。。严肃地说:我正在寻找一个python解决方案,因为代码适用于所有平台。Windows至少有24或25年的历史。第1版大约在1985年左右问世。您多大了?44.5(最后一次使用Unix是在18岁)请注意,这与的建议基本相同,因此对于大于4GB的文件无效..tell()非常有效。我要找的是原始文件的大小。最后4个字节是“原始(未压缩)输入数据的大小,模为2^32。”()我想这已经足够好了。对于大于4G的文件,如果tell()表明我们离ISIZE太近,则可以在进度栏中添加一些启发式设置,将文件大小设置为4G+ISIZE。我需要做同样的事情,并且我正在尝试扩展GzipFile类以提供文件大小,但我没有成功,你是如何让它工作的?更新:这个函数对我来说是有效的:注意,这并不是完全可靠的,因为附加到的gzip文件只有最后附加部分的大小。。。请参阅:-这里的第二个“1000”实际上应该是2000,但它只是附加的最后一个块的大小…如果文件很大怎么办?请注意,正如@allyourcode在这里所建议的,
len(df.read())
强制Python将整个文件保存在内存中。对于非常大的文件,这可能会使您的进程崩溃。打开文件
“rb”
以避免
错误:解包需要长度为4的字符串参数。这正是老Jorge Israel Peña的答案中显示的内容,因此,尽管您的答案提供了一个方便的函数,但它并不会给主题增加太多内容。此外,正如旧答案中的注释所说,仅仅依靠最后4个字节实际上并不是100%万无一失的,因为GZ允许您在filei.e的末尾附加新的块
file\u size=file\u obj.seek(0,io.seek\u END)
python3!没有Python 2 tho<代码>值错误:不支持从末端搜索
。但是:struct.unpack在2.7上工作!马克,我最近在做一些gzip文件的编程操作,经常会看到你的许多答案在堆栈的底部有一两张选票。我猜人们不认识你。感谢您的巨大贡献,感谢您在缺乏认可的情况下为压缩问题提供答案。
import struct

def getuncompressedsize(filename):
    with open(filename, 'rb') as f:
        f.seek(-4, 2)
        return struct.unpack('I', f.read(4))[0]
with gzip.open(filepath, 'rb') as file_obj:
    file_size = file_obj.seek(0, io.SEEK_END)