GZIPOutputStream与ByteArrayOutputStream共同使用时,先把数据存到baos,再写入文件,出现了以下错误
java.io.EOFException : Unexpected end of ZLIB input stream
at java.util.zip.InflaterInputStream.fill( InflaterInputStream.java:240)
at java.util.zip.InflaterInputStream.read( InflaterInputStream.java:158)
at java.util.zip.GZIPInputStream.read( GZIPInputStream.java:117)
at java.io.FilterInputStream.read( FilterInputStream.java:107)
at TestGzip.main( TestGzip.java:29)
查看文件大小,与直接使用FileOutputStream写的不一致,要小很多,究其原因,是数据没有完全刷到baos中。
翻看源码发现,gzip等压缩流在close时,会调用finish方法,完成流的转换,此处使用baos,在close之前就去取值,从而导致流数据不完整。
若想提前使用baos获取全部流数据,需要手动执行finish方法,进行手动刷新。
测试代码如下:
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class TestGzip {
public static void main(String[] args) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(baos );
FileOutputStream fos = new FileOutputStream("d://1.txt" );) {
gzip.write( "test".getBytes("UTF-8" ));
//gzip 只调用flush不会刷新
gzip.flush();
//压缩类型的流需要执行close或者finish才会完成
// gzip.finish();
fos.write( baos.toByteArray());
} catch (Exception e ) {
e.printStackTrace();
}
try (InputStream in = new GZIPInputStream(new FileInputStream("d://1.txt" ));
FileOutputStream fos = new FileOutputStream("d://2.txt" )) {
int len = -1;
byte[] buff = new byte[4096];
while ((len = in .read(buff )) > 0) {
fos.write( buff, 0, len);
}
} catch (Exception e ) {
e.printStackTrace();
}
}
}