获取python中.gz文件的未压缩大小
使用gzip,tell()返回未压缩文件中的偏移量。获取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() ? 在执行此操作之前,可能
为了显示进度条,我想知道文件的原始(未压缩)大小。
有没有一个简单的方法可以找到 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)