我是一个大型压缩文件,我想知道内容的大小而不解压缩它。我试过这个:
import gzip
import os
with gzip.open(data_file) as f:
f.seek(0, os.SEEK_END)
size = f.tell()
但我收到此错误
ValueError: Seek from end not supported
我该怎么做?
THX。
答案 0 :(得分:2)
不幸的是,Python 2.x gzip
module似乎不支持任何确定未压缩文件大小的方法。
但是,gzip
会将未压缩的文件大小存储为文件末尾的小端32位无符号整数:http://www.abeel.be/content/determine-uncompressed-size-gzip-file
不幸的是,这仅适用于大小<4gb 的文件,因为只使用了gzip
格式的32位整数;见the manual。
import os
import struct
with open(data_file,"rb") as f:
f.seek(-4, os.SEEK_END)
size, = struct.unpack("<I", f.read(4))
print size
答案 1 :(得分:2)
原则上不可能在没有解压缩的情况下明确地确定gzip文件中未压缩数据的大小。您不需要有空间来存储未压缩的数据 - 您可以随时丢弃它。但你必须全部解压缩。
如果您控制gzip文件的来源并且可以确保a)gzip文件中没有连接成员,b)未压缩数据的长度小于4 GB,并且c)没有任何无关的垃圾gzip文件的结尾,然后只有你可以读取gzip文件的最后四个字节,以获得一个具有未压缩数据长度的小端整数。
有关详细信息,请参阅this answer。
这是Python代码,用于读取gzip文件并打印未压缩的长度,而无需存储或保存未压缩的数据。它将内存使用限制为小缓冲区。这需要Python 3.3或更高版本:
#!/usr/local/bin/python3.4
import sys
import zlib
import warnings
f = open(sys.argv[1], "rb")
total = 0
buf = f.read(1024)
while True: # loop through concatenated gzip streams
z = zlib.decompressobj(15+16)
while True: # loop through one gzip stream
while True: # go through all output from one input buffer
total += len(z.decompress(buf, 4096))
buf = z.unconsumed_tail
if buf == b"":
break
if z.eof:
break # end of a gzip stream found
buf = f.read(1024)
if buf == b"":
warnings.warn("incomplete gzip stream")
break
buf = z.unused_data
z = None
if buf == b"":
buf == f.read(1024)
if buf == b"":
break
print(total)
答案 2 :(得分:-1)
总结一下,我需要打开huges压缩文件(> 4GB),因此Dan的技术不起作用,我想要文件的长度(行数),所以Mark Adler的技术是不合适的。
最终,我发现未压缩文件的解决方案(不是最优化的,但它可以工作!),可以轻松转换为压缩文件:
size = 0
with gzip.open(data_file) as f:
for line in f:
size+= 1
pass
return size
谢谢大家,本论坛的人非常有效!