KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > zip > GZIPInputStream


1 /*
2  * @(#)GZIPInputStream.java 1.29 06/03/03
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util.zip;
9
10 import java.io.SequenceInputStream JavaDoc;
11 import java.io.ByteArrayInputStream JavaDoc;
12 import java.io.InputStream JavaDoc;
13 import java.io.IOException JavaDoc;
14 import java.io.EOFException JavaDoc;
15
16 /**
17  * This class implements a stream filter for reading compressed data in
18  * the GZIP file format.
19  *
20  * @see InflaterInputStream
21  * @version 1.29, 03/03/06
22  * @author David Connelly
23  *
24  */

25 public
26 class GZIPInputStream extends InflaterInputStream JavaDoc {
27     /**
28      * CRC-32 for uncompressed data.
29      */

30     protected CRC32 JavaDoc crc = new CRC32 JavaDoc();
31
32     /**
33      * Indicates end of input stream.
34      */

35     protected boolean eos;
36
37     private boolean closed = false;
38     
39     /**
40      * Check to make sure that this stream has not been closed
41      */

42     private void ensureOpen() throws IOException JavaDoc {
43     if (closed) {
44         throw new IOException JavaDoc("Stream closed");
45         }
46     }
47
48     /**
49      * Creates a new input stream with the specified buffer size.
50      * @param in the input stream
51      * @param size the input buffer size
52      * @exception IOException if an I/O error has occurred
53      * @exception IllegalArgumentException if size is <= 0
54      */

55     public GZIPInputStream(InputStream JavaDoc in, int size) throws IOException JavaDoc {
56     super(in, new Inflater JavaDoc(true), size);
57         usesDefaultInflater = true;
58     readHeader();
59     crc.reset();
60     }
61
62     /**
63      * Creates a new input stream with a default buffer size.
64      * @param in the input stream
65      * @exception IOException if an I/O error has occurred
66      */

67     public GZIPInputStream(InputStream JavaDoc in) throws IOException JavaDoc {
68     this(in, 512);
69     }
70
71     /**
72      * Reads uncompressed data into an array of bytes. Blocks until enough
73      * input is available for decompression.
74      * @param buf the buffer into which the data is read
75      * @param off the start offset of the data
76      * @param len the maximum number of bytes read
77      * @return the actual number of bytes read, or -1 if the end of the
78      * compressed input stream is reached
79      * @exception IOException if an I/O error has occurred or the compressed
80      * input data is corrupt
81      */

82     public int read(byte[] buf, int off, int len) throws IOException JavaDoc {
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     /**
98      * Closes this input stream and releases any system resources associated
99      * with the stream.
100      * @exception IOException if an I/O error has occurred
101      */

102     public void close() throws IOException JavaDoc {
103         if (!closed) {
104             super.close();
105             eos = true;
106             closed = true;
107         }
108     }
109
110     /**
111      * GZIP header magic number.
112      */

113     public final static int GZIP_MAGIC = 0x8b1f;
114
115     /*
116      * File header flags.
117      */

118     private final static int FTEXT = 1; // Extra text
119
private final static int FHCRC = 2; // Header CRC
120
private final static int FEXTRA = 4; // Extra field
121
private final static int FNAME = 8; // File name
122
private final static int FCOMMENT = 16; // File comment
123

124     /*
125      * Reads GZIP member header.
126      */

127     private void readHeader() throws IOException JavaDoc {
128     CheckedInputStream JavaDoc in = new CheckedInputStream JavaDoc(this.in, crc);
129     crc.reset();
130     // Check header magic
131
if (readUShort(in) != GZIP_MAGIC) {
132         throw new IOException JavaDoc("Not in GZIP format");
133     }
134     // Check compression method
135
if (readUByte(in) != 8) {
136         throw new IOException JavaDoc("Unsupported compression method");
137     }
138     // Read flags
139
int flg = readUByte(in);
140     // Skip MTIME, XFL, and OS fields
141
skipBytes(in, 6);
142     // Skip optional extra field
143
if ((flg & FEXTRA) == FEXTRA) {
144         skipBytes(in, readUShort(in));
145     }
146     // Skip optional file name
147
if ((flg & FNAME) == FNAME) {
148         while (readUByte(in) != 0) ;
149     }
150     // Skip optional file comment
151
if ((flg & FCOMMENT) == FCOMMENT) {
152         while (readUByte(in) != 0) ;
153     }
154     // Check optional header CRC
155
if ((flg & FHCRC) == FHCRC) {
156         int v = (int)crc.getValue() & 0xffff;
157         if (readUShort(in) != v) {
158         throw new IOException JavaDoc("Corrupt GZIP header");
159         }
160     }
161     }
162
163     /*
164      * Reads GZIP member trailer.
165      */

166     private void readTrailer() throws IOException JavaDoc {
167     InputStream JavaDoc in = this.in;
168     int n = inf.getRemaining();
169     if (n > 0) {
170         in = new SequenceInputStream JavaDoc(
171             new ByteArrayInputStream JavaDoc(buf, len - n, n), in);
172     }
173         // Uses left-to-right evaluation order
174
if ((readUInt(in) != crc.getValue()) ||
175             // rfc1952; ISIZE is the input size modulo 2^32
176
(readUInt(in) != (inf.getBytesWritten() & 0xffffffffL)))
177             throw new IOException JavaDoc("Corrupt GZIP trailer");
178     }
179
180     /*
181      * Reads unsigned integer in Intel byte order.
182      */

183     private long readUInt(InputStream JavaDoc in) throws IOException JavaDoc {
184     long s = readUShort(in);
185     return ((long)readUShort(in) << 16) | s;
186     }
187
188     /*
189      * Reads unsigned short in Intel byte order.
190      */

191     private int readUShort(InputStream JavaDoc in) throws IOException JavaDoc {
192     int b = readUByte(in);
193     return ((int)readUByte(in) << 8) | b;
194     }
195
196     /*
197      * Reads unsigned byte.
198      */

199     private int readUByte(InputStream JavaDoc in) throws IOException JavaDoc {
200     int b = in.read();
201     if (b == -1) {
202         throw new EOFException JavaDoc();
203     }
204     return b;
205     }
206
207
208     private byte[] tmpbuf = new byte[128];
209
210     /*
211      * Skips bytes of input data blocking until all bytes are skipped.
212      * Does not assume that the input stream is capable of seeking.
213      */

214     private void skipBytes(InputStream JavaDoc in, int n) throws IOException JavaDoc {
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 JavaDoc();
219         }
220         n -= len;
221     }
222     }
223 }
224
Popular Tags