Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/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
Java 获取gzip文件属性(如';gzip-l';,基本上是压缩比)_Java_Gzip - Fatal编程技术网

Java 获取gzip文件属性(如';gzip-l';,基本上是压缩比)

Java 获取gzip文件属性(如';gzip-l';,基本上是压缩比),java,gzip,Java,Gzip,我有一个非常大的gzip文件树目录,我需要计算未压缩的大小。 正如我所说的超过600GB的压缩文件一样,我认为解压缩每个文件以验证大小不是正确的方法 在Unixshell上,我通过使用命令gzip-l轻松完成这项任务,在文件夹中列出每个文件的压缩比、压缩大小和未压缩大小 尽管如此,我发现的与GZIP相关的Java库只是用于压缩和解压缩的流 如果gzip命令可以在不接触文件的情况下检索此信息,我假设必须在文件的某种头上指定此数据。在不解压缩文件的情况下访问这些信息的方法是什么?看看Apache C

我有一个非常大的gzip文件树目录,我需要计算未压缩的大小。 正如我所说的超过600GB的压缩文件一样,我认为解压缩每个文件以验证大小不是正确的方法

Unix
shell上,我通过使用命令
gzip-l
轻松完成这项任务,在文件夹中列出每个文件的压缩比、压缩大小和未压缩大小

尽管如此,我发现的与
GZIP
相关的Java库只是用于压缩和解压缩的流


如果
gzip
命令可以在不接触文件的情况下检索此信息,我假设必须在文件的某种头上指定此数据。在不解压缩文件的情况下访问这些信息的方法是什么?

看看Apache Commons Compress,它支持gzip。它还有一个类“org.apache.commons.compress.compressors.gzip.gzip参数”,可能会有所帮助。

根据gzip规范,gzip块的最后4个字节是数据的未压缩大小。该值存储在little endian中。大多数gzip文件只有1个块,因此这将是文件的最后4个字节

例如,我刚刚压缩了一个未压缩大小为29963246字节的文件。gzip文件中的最后4个字节是

EE 33 C9 01

当读取小端时(从右到左)0x1C933EE=29963246

这里有一种快速而肮脏的方法,通过只读取little endian中的最后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个字节,我假设一个大于4GB的文件将被分割成多个GZIP块


更健壮的版本是解析每个gzip块,以获得每个块的未压缩大小。GZIP头还具有压缩数据的大小,因此您必须解析每个GZIP块头,获取压缩数据的长度,查找该长度以获取GZIP块的结尾,然后获取要汇总的未压缩大小。然后继续解析任何附加的GZIP块,直到到达EOF。

也就是说。。。实际上很有趣-再一次:文档/规范FTW!谢谢哇!对于未压缩的大小,它检索到的值与
gzip-l
命令的值完全相同。没有(或者至少很容易找到)用于这些操作的API不是很奇怪吗?无论如何,非常感谢你的回答。@Netto没问题。我想象
gzip-l
做了我在上一段中描述的事情如果你的文件大于2GB,那么最后一次调用getInt()会溢出,如果你的文件大于4GB,然后我会认为压缩文件将在多个块中,您将不得不执行我在帖子末尾描述的更复杂的解析。当我看到以字节为单位的大小的int值时,我会这样想。你有没有相关的提示来识别文件中的gzip块?这很有趣。我能够访问我的GZIP文件的
GZIP参数
实例。不幸的是,它似乎只有压缩机的参数。我在这个类中找到的最有用的方法是
gzip参数.getCompressionLevel()
,但它为我的文件检索
-1
。不管怎样,谢谢。看。那很有趣。非常感谢。