001 /* DeflaterOutputStream.java - Output filter for compressing.
002 Copyright (C) 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath 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 for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package java.util.zip;
040
041 import java.io.FilterOutputStream;
042 import java.io.IOException;
043 import java.io.OutputStream;
044
045 /* Written using on-line Java Platform 1.2 API Specification
046 * and JCL book.
047 * Believed complete and correct.
048 */
049
050 /**
051 * This is a special FilterOutputStream deflating the bytes that are
052 * written through it. It uses the Deflater for deflating.
053 *
054 * A special thing to be noted is that flush() doesn't flush
055 * everything in Sun's JDK, but it does so in jazzlib. This is because
056 * Sun's Deflater doesn't have a way to flush() everything, without
057 * finishing the stream.
058 *
059 * @author Tom Tromey, Jochen Hoenicke
060 * @date Jan 11, 2001
061 */
062 public class DeflaterOutputStream extends FilterOutputStream
063 {
064 /**
065 * This buffer is used temporarily to retrieve the bytes from the
066 * deflater and write them to the underlying output stream.
067 */
068 protected byte[] buf;
069
070 /**
071 * The deflater which is used to deflate the stream.
072 */
073 protected Deflater def;
074
075 /**
076 * Deflates everything in the def's input buffers. This will call
077 * <code>def.deflate()</code> until all bytes from the input buffers
078 * are processed.
079 */
080 protected void deflate() throws IOException
081 {
082 while (! def.needsInput())
083 {
084 int len = def.deflate(buf, 0, buf.length);
085
086 // System.err.println("DOS deflated " + len + " out of " + buf.length);
087 if (len <= 0)
088 break;
089 out.write(buf, 0, len);
090 }
091
092 if (! def.needsInput())
093 throw new InternalError("Can't deflate all input?");
094 }
095
096 /**
097 * Creates a new DeflaterOutputStream with a default Deflater and
098 * default buffer size.
099 * @param out the output stream where deflated output should be written.
100 */
101 public DeflaterOutputStream(OutputStream out)
102 {
103 this(out, new Deflater(), 4096);
104 }
105
106 /**
107 * Creates a new DeflaterOutputStream with the given Deflater and
108 * default buffer size.
109 * @param out the output stream where deflated output should be written.
110 * @param defl the underlying deflater.
111 */
112 public DeflaterOutputStream(OutputStream out, Deflater defl)
113 {
114 this(out, defl, 4096);
115 }
116
117 /**
118 * Creates a new DeflaterOutputStream with the given Deflater and
119 * buffer size.
120 * @param out the output stream where deflated output should be written.
121 * @param defl the underlying deflater.
122 * @param bufsize the buffer size.
123 * @exception IllegalArgumentException if bufsize isn't positive.
124 */
125 public DeflaterOutputStream(OutputStream out, Deflater defl, int bufsize)
126 {
127 super(out);
128 if (bufsize <= 0)
129 throw new IllegalArgumentException("bufsize <= 0");
130 buf = new byte[bufsize];
131 def = defl;
132 }
133
134 /**
135 * Flushes the stream by calling flush() on the deflater and then
136 * on the underlying stream. This ensures that all bytes are
137 * flushed. This function doesn't work in Sun's JDK, but only in
138 * jazzlib.
139 */
140 public void flush() throws IOException
141 {
142 def.flush();
143 deflate();
144 out.flush();
145 }
146
147 /**
148 * Finishes the stream by calling finish() on the deflater. This
149 * was the only way to ensure that all bytes are flushed in Sun's
150 * JDK.
151 */
152 public void finish() throws IOException
153 {
154 def.finish();
155 while (! def.finished())
156 {
157 int len = def.deflate(buf, 0, buf.length);
158 if (len <= 0)
159 break;
160 out.write(buf, 0, len);
161 }
162 if (! def.finished())
163 throw new InternalError("Can't deflate all input?");
164 out.flush();
165 }
166
167 /**
168 * Calls finish() and closes the stream.
169 */
170 public void close() throws IOException
171 {
172 finish();
173 out.close();
174 }
175
176 /**
177 * Writes a single byte to the compressed output stream.
178 * @param bval the byte value.
179 */
180 public void write(int bval) throws IOException
181 {
182 byte[] b = new byte[1];
183 b[0] = (byte) bval;
184 write(b, 0, 1);
185 }
186
187 /**
188 * Writes a len bytes from an array to the compressed stream.
189 * @param buf the byte array.
190 * @param off the offset into the byte array where to start.
191 * @param len the number of bytes to write.
192 */
193 public void write(byte[] buf, int off, int len) throws IOException
194 {
195 def.setInput(buf, off, len);
196 deflate();
197 }
198 }