这是《水煮 JDK 源码》系列 的第4篇文章,计划撰写100篇关于JDK源码相关的文章
GZIPInputStream
类位于 java.util.zip
包下,继承于 InflaterInputStream
类,它实现了一个流式过滤器,主要用于读取GZIP文件格式的压缩数据,其UML类图如下:
类声明如下:
public class GZIPInputStream extends InflaterInputStream
1、成员变量
GZIPInputStream
定义了3个成员变量,分别如下:
/** CRC-32 用于未压缩的数据 */
protected CRC32 crc = new CRC32();
/** 表示输入流的结尾状态 */
protected boolean eos;
/** 输入流是否已关闭的状态 */
private boolean closed = false;
2、构造函数
创建 GZIPInputStream
压缩输入流主要有以下的两种方式:
/** 使用默认大小的缓冲区创建新的输入流 */
public GZIPInputStream(InputStream in) throws IOException {
// 默认缓冲区大小为512
this(in, 512);
}
/** 使用指定大小的缓冲区创建新的输入流 */
public GZIPInputStream(InputStream in, int size) throws IOException {
// 调用父类 InflaterInputStream 的构造函数
super(in, new Inflater(true), size);
// 设置父类 InflaterInputStream 的 usesDefaultInflater
// 表示使用默认的解压缩器
usesDefaultInflater = true;
// 读取 GZIP 的成员头信息,并返回头信息的总字节数
readHeader(in);
}
由于 GZIPInputStream
是由于读取压缩数据的输入流,因此需要用到解压缩器 Inflater
。
3、读取数据方法
GZIPInputStream
主要提供了1个用于读取流数据的方法,如下:
public int read(byte[] buf, int off, int len) throws IOException {
// 在正式读取流数据之前,要确保流没有被关闭
ensureOpen();
// 如果已经到了流的结尾,说明没有可读的数据了,直接返回 -1
if (eos) {
return -1;
}
// 调用父类 InflaterInputStream 的 read() 方法读取数据
int n = super.read(buf, off, len);
// 如果实际读取到的数据为 -1,说明没有可读数据
if (n == -1) {
// 读取 GZIP 的成员尾部信息,判断是否读取到了 eos
// 如果是,则将 eos 置为 true,表示已读取到了尾部
if (readTrailer())
eos = true;
else
// 否则,继续调用本方法进行读取
return this.read(buf, off, len);