在GZIP文件中查找文件的大小

有没有办法找出原始文件的大小在java中的GZIP文件中?

就像在,我有一个15 MB的文件a.txt已被GZip压缩到3GB的a.gz。 我想知道a.gz中存在的a.txt的大小,而不解压缩a.gz.

除了枪杀流之外,没有真正可靠的方法。 您不需要保存解压缩的结果,因此您可以通过简单地读取和解码整个文件来确定大小,而不会占用解压缩结果的空间。

有一种不可靠的方法来确定未压缩的大小,即查看gzip文件的最后四个字节,即以小端序排列的模232的未压缩长度。

这是不可靠的,因为a)未压缩的数据可能长于2 32个字节,并且b)gzip文件可能包含多个gzip流,在这种情况下,您将只找到最后一个流的长度。

如果您控制gzip文件的源代码,您就知道它们由单个gzip流组成,并且您知道它们的压缩率小于2 32个字节,那么只有这样才可以放心地使用最后四个字节。

pigz(可以在http://zlib.net/pigz/找到)可以做到这两点 。 pigz -l会很快给你不可靠的长度。 pigz -lt将解码整个输入并为您提供可靠的长度。

下面是解决这个问题的一种方法 – 当然不是最好的方法,但是由于Java没有为此提供API方法(与处理Zip文件不同),这是我能想到的唯一方法,除了其中一个上面的评论,谈到了最后4个字节的读取(假设文件大小在2Gb以下)。

 GZIPInputStream zis = new GZIPInputStream(new FileInputStream(new File("myFile.gz"))); long size = 0; while (zis.available() > 0) { byte[] buf = new byte[1024]; int read = zis.read(buf); if (read > 0) size += read; } System.out.println("File Size: " + size + "bytes"); zis.close(); 

如您所见,读入gzip文件,并读入读入的字节数,表示未压缩的文件大小。

虽然这种方法确实有效,但我真的不建议将它用于非常大的文件,因为这可能需要几秒钟。 (除非时间不是太大的约束)

 public class ReadStream { public static void main(String[] args) { try { RandomAccessFile raf = new RandomAccessFile(new File("D:/temp/temp.gz"), "r"); try { raf.seek(raf.length() - 4); int b4 = raf.read(); int b3 = raf.read(); int b2 = raf.read(); int b1 = raf.read(); int val = (b1 << 24) | (b2 << 16) + (b3 << 8) + b4; System.out.println(val); raf.close(); } catch (IOException ex) { Logger.getLogger(ReadStream.class.getName()).log(Level.SEVERE, null, ex); } } catch (FileNotFoundException ex) { Logger.getLogger(ReadStream.class.getName()).log(Level.SEVERE, null, ex); } } } 

GZIP不会提前告知您内容的大小。 根据您的要求,这些是我能想到的管理方式:

  1. 在运行中解压缩流,如果它太大则中止
  2. 解压缩流但不写出内容。 这会得到
  3. 未压缩数据的大小,不占用任何空间。 它只需要处理读取和膨胀
  4. 切换到使用zip文件(其中包含可以提前告诉您长度的条目)
  5. 如果您知道通常接收的数据类型,则可以根据压缩gzip的大小统计估计大小。