有没有办法找出java中GZIP文件中原始文件的大小?
就像在,我有一个15 MB的文件a.txt已被GZip压缩到3GB的a.gz。我想知道a.gz中存在的a.txt的大小,而不解压缩a.gz。
答案 0 :(得分:22)
除了枪杀流之外,没有真正可靠的方法。您不需要保存解压缩的结果,因此您可以通过简单地读取和解码整个文件来确定大小,而不会占用解压缩结果的空间。
有一种不可靠的方法来确定未压缩的大小,即查看gzip文件的最后四个字节,这是以小端顺序模2 32 的条目的未压缩长度
这是不可靠的,因为a)未压缩的数据可能长于2 32 字节,而b)gzip文件可能包含多个gzip流,在这种情况下你会发现只有长度这些流中的最后一个。
如果您控制gzip文件的源代码,您就会知道它们由单个gzip流组成,并且您知道它们的压缩率小于2 32 字节,然后才会你可以放心地使用最后四个字节。
pigz(可以在http://zlib.net/pigz/找到)可以双向完成。 pigz -l会很快给你不可靠的长度。 pigz -lt将解码整个输入并为您提供可靠的长度。
答案 1 :(得分:4)
下面是针对此问题的一种方法 - 当然不是最好的方法,但是由于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文件,读入的字节数总计为未压缩文件大小。
虽然这种方法确实有效,但我真的不建议将它用于非常大的文件,因为这可能需要几秒钟。 (除非时间不是太大的约束)
答案 2 :(得分:2)
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);
}
}
}
答案 3 :(得分:0)
GZIP不会提前告知您内容的大小。根据您的要求,这些是我可以想到的管理方式: