KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)InflaterOutputStream.java 1.1 06/02/28
3  *
4  * Copyright 2006 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.FilterOutputStream JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.io.OutputStream JavaDoc;
13
14 /**
15  * Implements an output stream filter for uncompressing data stored in the
16  * "deflate" compression format.
17  *
18  * @version 1.1
19  * @since 1.6
20  * @author David R Tribble (david@tribble.com)
21  *
22  * @see InflaterInputStream
23  * @see DeflaterInputStream
24  * @see DeflaterOutputStream
25  */

26
27 public class InflaterOutputStream extends FilterOutputStream JavaDoc {
28     /** Decompressor for this stream. */
29     protected final Inflater JavaDoc inf;
30
31     /** Output buffer for writing uncompressed data. */
32     protected final byte[] buf;
33
34     /** Temporary write buffer. */
35     private final byte[] wbuf = new byte[1];
36
37     /** Default decompressor is used. */
38     private boolean usesDefaultInflater = false;
39
40     /** true iff {@link #close()} has been called. */
41     private boolean closed = false;
42     
43     /**
44      * Checks to make sure that this stream has not been closed.
45      */

46     private void ensureOpen() throws IOException JavaDoc {
47         if (closed) {
48             throw new IOException JavaDoc("Stream closed");
49         }
50     }
51     
52     /**
53      * Creates a new output stream with a default decompressor and buffer
54      * size.
55      *
56      * @param out output stream to write the uncompressed data to
57      * @throws NullPointerException if {@code out} is null
58      */

59     public InflaterOutputStream(OutputStream JavaDoc out) {
60         this(out, new Inflater JavaDoc());
61         usesDefaultInflater = true;
62     }
63
64     /**
65      * Creates a new output stream with the specified decompressor and a
66      * default buffer size.
67      *
68      * @param out output stream to write the uncompressed data to
69      * @param infl decompressor ("inflater") for this stream
70      * @throws NullPointerException if {@code out} or {@code infl} is null
71      */

72     public InflaterOutputStream(OutputStream JavaDoc out, Inflater JavaDoc infl) {
73         this(out, infl, 512);
74     }
75
76     /**
77      * Creates a new output stream with the specified decompressor and
78      * buffer size.
79      *
80      * @param out output stream to write the uncompressed data to
81      * @param infl decompressor ("inflater") for this stream
82      * @param bufLen decompression buffer size
83      * @throws IllegalArgumentException if {@code bufLen} is <= 0
84      * @throws NullPointerException if {@code out} or {@code infl} is null
85      */

86     public InflaterOutputStream(OutputStream JavaDoc out, Inflater JavaDoc infl, int bufLen) {
87         super(out);
88
89         // Sanity checks
90
if (out == null)
91             throw new NullPointerException JavaDoc("Null output");
92         if (infl == null)
93             throw new NullPointerException JavaDoc("Null inflater");
94         if (bufLen <= 0)
95             throw new IllegalArgumentException JavaDoc("Buffer size < 1");
96
97         // Initialize
98
inf = infl;
99         buf = new byte[bufLen];
100     }
101
102     /**
103      * Writes any remaining uncompressed data to the output stream and closes
104      * the underlying output stream.
105      *
106      * @throws IOException if an I/O error occurs
107      */

108     public void close() throws IOException JavaDoc {
109         if (!closed) {
110             // Complete the uncompressed output
111
try {
112                 finish();
113             } finally {
114                 out.close();
115                 closed = true;
116             }
117         }
118     }
119
120     /**
121      * Flushes this output stream, forcing any pending buffered output bytes to be
122      * written.
123      *
124      * @throws IOException if an I/O error occurs or this stream is already
125      * closed
126      */

127     public void flush() throws IOException JavaDoc {
128         ensureOpen();
129
130         // Finish decompressing and writing pending output data
131
if (!inf.finished()) {
132             try {
133                 while (!inf.finished() && !inf.needsInput()) {
134                     int n;
135
136                     // Decompress pending output data
137
n = inf.inflate(buf, 0, buf.length);
138                     if (n < 1) {
139                         break;
140                     }
141
142                     // Write the uncompressed output data block
143
out.write(buf, 0, n);
144                 }
145                 super.flush();
146             } catch (DataFormatException JavaDoc ex) {
147                 // Improperly formatted compressed (ZIP) data
148
String JavaDoc msg = ex.getMessage();
149                 if (msg == null) {
150                     msg = "Invalid ZLIB data format";
151                 }
152                 throw new ZipException JavaDoc(msg);
153             }
154         }
155     }
156
157     /**
158      * Finishes writing uncompressed data to the output stream without closing
159      * the underlying stream. Use this method when applying multiple filters in
160      * succession to the same output stream.
161      *
162      * @throws IOException if an I/O error occurs or this stream is already
163      * closed
164      */

165     public void finish() throws IOException JavaDoc {
166         ensureOpen();
167
168         // Finish decompressing and writing pending output data
169
flush();
170         if (usesDefaultInflater) {
171             inf.end();
172         }
173     }
174
175     /**
176      * Writes a byte to the uncompressed output stream.
177      *
178      * @param b a single byte of compressed data to decompress and write to
179      * the output stream
180      * @throws IOException if an I/O error occurs or this stream is already
181      * closed
182      * @throws ZipException if a compression (ZIP) format error occurs
183      */

184     public void write(int b) throws IOException JavaDoc {
185         // Write a single byte of data
186
wbuf[0] = (byte) b;
187         write(wbuf, 0, 1);
188     }
189
190     /**
191      * Writes an array of bytes to the uncompressed output stream.
192      *
193      * @param b buffer containing compressed data to decompress and write to
194      * the output stream
195      * @param off starting offset of the compressed data within {@code b}
196      * @param len number of bytes to decompress from {@code b}
197      * @throws IndexOutOfBoundsException if {@code off} < 0, or if
198      * {@code len} < 0, or if {@code len} > {@code b.length - off}
199      * @throws IOException if an I/O error occurs or this stream is already
200      * closed
201      * @throws NullPointerException if {@code b} is null
202      * @throws ZipException if a compression (ZIP) format error occurs
203      */

204     public void write(byte[] b, int off, int len) throws IOException JavaDoc {
205         // Sanity checks
206
ensureOpen();
207         if (b == null) {
208             throw new NullPointerException JavaDoc("Null buffer for read");
209         } else if (off < 0 || len < 0 || len > b.length - off) {
210             throw new IndexOutOfBoundsException JavaDoc();
211         } else if (len == 0) {
212             return;
213         }
214
215         // Write uncompressed data to the output stream
216
try {
217             for (;;) {
218                 int n;
219
220                 // Fill the decompressor buffer with output data
221
if (inf.needsInput()) {
222                     int part;
223
224                     if (len < 1) {
225                         break;
226                     }
227
228                     part = (len < 512 ? len : 512);
229                     inf.setInput(b, off, part);
230                     off += part;
231                     len -= part;
232                 }
233
234                 // Decompress and write blocks of output data
235
do {
236                     n = inf.inflate(buf, 0, buf.length);
237                     if (n > 0) {
238                         out.write(buf, 0, n);
239                     }
240                 } while (n > 0);
241
242                 // Check the decompressor
243
if (inf.finished()) {
244                     break;
245                 }
246                 if (inf.needsDictionary()) {
247                     throw new ZipException JavaDoc("ZLIB dictionary missing");
248                 }
249             }
250         } catch (DataFormatException JavaDoc ex) {
251             // Improperly formatted compressed (ZIP) data
252
String JavaDoc msg = ex.getMessage();
253             if (msg == null) {
254                 msg = "Invalid ZLIB data format";
255             }
256             throw new ZipException JavaDoc(msg);
257         }
258     }
259 }
260
Popular Tags