我有一个非常大的gzip文件树目录,我需要计算未压缩的大小。
由于我所说的不仅仅是600GB
(已压缩),我相信解压缩每个文件以验证大小并不是正确的方法。
在Unix
shell上,我使用命令gzip -l
轻松完成此任务,列出压缩比,压缩和未压缩大小的文件夹上的每个文件。
虽然,我发现的与GZIP
相关的Java库只是用于压缩和解压缩的Streams。
如果gzip
命令可以在不触及文件的情况下检索此信息,我认为必须在文件的某种标题上指定此数据。在不解压缩文件的情况下访问此信息的方法是什么?
答案 0 :(得分:3)
根据GZIP规范RFC 1952,GZIP块的最后4个字节是未压缩的数据大小。该值存储在little endian中。大多数gzip压缩文件只有1个块,因此这将是文件的最后4个字节。
例如,我只是压缩了一个未压缩大小为29963246字节的文件。 gzip文件中的最后4个字节是
EE 33 C9 01
当读取小端(从右到左)0x1C933EE = 29963246
时这里只是通过读取小端的最后4个字节来快速而肮脏地获取未压缩文件的大小:
File f = ...
try(RandomAccessFile ra =new RandomAccessFile(f, "r");
FileChannel channel = ra.getChannel()){
MappedByteBuffer fileBuffer = channel.map(MapMode.READ_ONLY, f.length()-4, 4);
fileBuffer.load();
ByteBuffer buf = ByteBuffer.allocate(4);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put(fileBuffer);
buf.flip();
//will print the uncompressed size
//getInt() reads the 4 bytes as a int
// if the file is between 2GB and 4GB
// then this will return a negative value
//and you'll have to do your own converting to an unsigned int
System.out.println(buf.getInt());
}
修改强>
请注意,这仅适用于仅有1个压缩块的gzip压缩文件(大多数文件<4GB)。如果您有一个包含多个gzip压缩块的文件,则只返回最后一个块的大小。由于规范只为该大小分配4个字节,我假设一个&gt; 4GB的文件将被分成多个GZIP块。
更强大的版本是解析每个gzip块以获得每个块的未压缩大小。 GZIP标头也具有压缩数据的大小,因此您必须解析每个GZIP块标头,获取压缩数据的长度,寻找该长度以获得GZIP块的结束,然后获得未压缩的大小以进行总结。然后继续解析任何其他GZIP块,直到你达到EOF。
答案 1 :(得分:0)
看看Apache Commons Compress,它支持gzip。它还有一个类&#39; org.apache.commons.compress.compressors.gzip.GzipParameters&#39;这可能会有所帮助。