001: /*
002: * @(#)DeflaterOutputStream.java 1.34 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.util.zip;
029:
030: import java.io.FilterOutputStream;
031: import java.io.OutputStream;
032: import java.io.InputStream;
033: import java.io.IOException;
034:
035: /**
036: * This class implements an output stream filter for compressing data in
037: * the "deflate" compression format. It is also used as the basis for other
038: * types of compression filters, such as GZIPOutputStream.
039: *
040: * @see Deflater
041: * @version 1.27, 02/02/00
042: * @author David Connelly
043: */
044: public class DeflaterOutputStream extends FilterOutputStream {
045: /**
046: * Compressor for this stream.
047: */
048: protected Deflater def;
049:
050: /**
051: * Output buffer for writing compressed data.
052: */
053: protected byte[] buf;
054:
055: /**
056: * Indicates that the stream has been closed.
057: */
058:
059: private boolean closed = false;
060:
061: /**
062: * Creates a new output stream with the specified compressor and
063: * buffer size.
064: * @param out the output stream
065: * @param def the compressor ("deflater")
066: * @param size the output buffer size
067: * @exception IllegalArgumentException if size is <= 0
068: */
069: public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
070: super (out);
071: if (out == null || def == null) {
072: throw new NullPointerException();
073: } else if (size <= 0) {
074: throw new IllegalArgumentException("buffer size <= 0");
075: }
076: this .def = def;
077: buf = new byte[size];
078: }
079:
080: /**
081: * Creates a new output stream with the specified compressor and
082: * a default buffer size.
083: * @param out the output stream
084: * @param def the compressor ("deflater")
085: */
086: public DeflaterOutputStream(OutputStream out, Deflater def) {
087: this (out, def, 512);
088: }
089:
090: boolean usesDefaultDeflater = false;
091:
092: /**
093: * Creates a new output stream with a defaul compressor and buffer size.
094: * @param out the output stream
095: */
096: public DeflaterOutputStream(OutputStream out) {
097: this (out, new Deflater());
098: usesDefaultDeflater = true;
099: }
100:
101: /**
102: * Writes a byte to the compressed output stream. This method will
103: * block until the byte can be written.
104: * @param b the byte to be written
105: * @exception IOException if an I/O error has occurred
106: */
107: public void write(int b) throws IOException {
108: byte[] buf = new byte[1];
109: buf[0] = (byte) (b & 0xff);
110: write(buf, 0, 1);
111: }
112:
113: /**
114: * Writes an array of bytes to the compressed output stream. This
115: * method will block until all the bytes are written.
116: * @param b the data to be written
117: * @param off the start offset of the data
118: * @param len the length of the data
119: * @exception IOException if an I/O error has occurred
120: */
121: public void write(byte[] b, int off, int len) throws IOException {
122: if (def.finished()) {
123: throw new IOException("write beyond end of stream");
124: }
125: if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
126: throw new IndexOutOfBoundsException();
127: } else if (len == 0) {
128: return;
129: }
130: if (!def.finished()) {
131: def.setInput(b, off, len);
132: while (!def.needsInput()) {
133: deflate();
134: }
135: }
136: }
137:
138: /**
139: * Finishes writing compressed data to the output stream without closing
140: * the underlying stream. Use this method when applying multiple filters
141: * in succession to the same output stream.
142: * @exception IOException if an I/O error has occurred
143: */
144: public void finish() throws IOException {
145: if (!def.finished()) {
146: def.finish();
147: while (!def.finished()) {
148: deflate();
149: }
150: }
151: }
152:
153: /**
154: * Writes remaining compressed data to the output stream and closes the
155: * underlying stream.
156: * @exception IOException if an I/O error has occurred
157: */
158: public void close() throws IOException {
159: if (!closed) {
160: finish();
161: if (usesDefaultDeflater)
162: def.end();
163: out.close();
164: closed = true;
165: }
166: }
167:
168: /**
169: * Writes next block of compressed data to the output stream.
170: * @throws IOException if an I/O error has occurred
171: */
172: protected void deflate() throws IOException {
173: int len = def.deflate(buf, 0, buf.length);
174: if (len > 0) {
175: out.write(buf, 0, len);
176: }
177: }
178: }
|