1 7 8 package java.util.zip; 9 10 import java.io.SequenceInputStream ; 11 import java.io.ByteArrayInputStream ; 12 import java.io.InputStream ; 13 import java.io.IOException ; 14 import java.io.EOFException ; 15 16 25 public 26 class GZIPInputStream extends InflaterInputStream { 27 30 protected CRC32 crc = new CRC32 (); 31 32 35 protected boolean eos; 36 37 private boolean closed = false; 38 39 42 private void ensureOpen() throws IOException { 43 if (closed) { 44 throw new IOException ("Stream closed"); 45 } 46 } 47 48 55 public GZIPInputStream(InputStream in, int size) throws IOException { 56 super(in, new Inflater (true), size); 57 usesDefaultInflater = true; 58 readHeader(); 59 crc.reset(); 60 } 61 62 67 public GZIPInputStream(InputStream in) throws IOException { 68 this(in, 512); 69 } 70 71 82 public int read(byte[] buf, int off, int len) throws IOException { 83 ensureOpen(); 84 if (eos) { 85 return -1; 86 } 87 len = super.read(buf, off, len); 88 if (len == -1) { 89 readTrailer(); 90 eos = true; 91 } else { 92 crc.update(buf, off, len); 93 } 94 return len; 95 } 96 97 102 public void close() throws IOException { 103 if (!closed) { 104 super.close(); 105 eos = true; 106 closed = true; 107 } 108 } 109 110 113 public final static int GZIP_MAGIC = 0x8b1f; 114 115 118 private final static int FTEXT = 1; private final static int FHCRC = 2; private final static int FEXTRA = 4; private final static int FNAME = 8; private final static int FCOMMENT = 16; 124 127 private void readHeader() throws IOException { 128 CheckedInputStream in = new CheckedInputStream (this.in, crc); 129 crc.reset(); 130 if (readUShort(in) != GZIP_MAGIC) { 132 throw new IOException ("Not in GZIP format"); 133 } 134 if (readUByte(in) != 8) { 136 throw new IOException ("Unsupported compression method"); 137 } 138 int flg = readUByte(in); 140 skipBytes(in, 6); 142 if ((flg & FEXTRA) == FEXTRA) { 144 skipBytes(in, readUShort(in)); 145 } 146 if ((flg & FNAME) == FNAME) { 148 while (readUByte(in) != 0) ; 149 } 150 if ((flg & FCOMMENT) == FCOMMENT) { 152 while (readUByte(in) != 0) ; 153 } 154 if ((flg & FHCRC) == FHCRC) { 156 int v = (int)crc.getValue() & 0xffff; 157 if (readUShort(in) != v) { 158 throw new IOException ("Corrupt GZIP header"); 159 } 160 } 161 } 162 163 166 private void readTrailer() throws IOException { 167 InputStream in = this.in; 168 int n = inf.getRemaining(); 169 if (n > 0) { 170 in = new SequenceInputStream ( 171 new ByteArrayInputStream (buf, len - n, n), in); 172 } 173 if ((readUInt(in) != crc.getValue()) || 175 (readUInt(in) != (inf.getBytesWritten() & 0xffffffffL))) 177 throw new IOException ("Corrupt GZIP trailer"); 178 } 179 180 183 private long readUInt(InputStream in) throws IOException { 184 long s = readUShort(in); 185 return ((long)readUShort(in) << 16) | s; 186 } 187 188 191 private int readUShort(InputStream in) throws IOException { 192 int b = readUByte(in); 193 return ((int)readUByte(in) << 8) | b; 194 } 195 196 199 private int readUByte(InputStream in) throws IOException { 200 int b = in.read(); 201 if (b == -1) { 202 throw new EOFException (); 203 } 204 return b; 205 } 206 207 208 private byte[] tmpbuf = new byte[128]; 209 210 214 private void skipBytes(InputStream in, int n) throws IOException { 215 while (n > 0) { 216 int len = in.read(tmpbuf, 0, n < tmpbuf.length ? n : tmpbuf.length); 217 if (len == -1) { 218 throw new EOFException (); 219 } 220 n -= len; 221 } 222 } 223 } 224 | Popular Tags |