2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package java.util.zip;
20 import java.io.FilterOutputStream;
21 import java.io.IOException;
22 import java.io.OutputStream;
25 * This class provides an implementation of {@code FilterOutputStream} that
26 * compresses data using the <i>DEFLATE</i> algorithm. Basically it wraps the
27 * {@code Deflater} class and takes care of the buffering.
31 public class DeflaterOutputStream extends FilterOutputStream {
32 static final int BUF_SIZE = 512;
35 * The buffer for the data to be written to.
42 protected Deflater def;
46 private final boolean syncFlush;
49 * This constructor lets you pass the {@code Deflater} specifying the
50 * compression algorithm.
53 * is the {@code OutputStream} where to write the compressed data
56 * is the specific {@code Deflater} that is used to compress
59 public DeflaterOutputStream(OutputStream os, Deflater def) {
60 this(os, def, BUF_SIZE, false);
64 * This is the most basic constructor. You only need to pass the {@code
65 * OutputStream} to which the compressed data shall be written to. The
66 * default settings for the {@code Deflater} and internal buffer are used.
67 * In particular the {@code Deflater} produces a ZLIB header in the output
71 * is the OutputStream where to write the compressed data to.
73 public DeflaterOutputStream(OutputStream os) {
74 this(os, new Deflater(), BUF_SIZE, false);
78 * This constructor lets you specify both the compression algorithm as well
79 * as the internal buffer size to be used.
82 * is the {@code OutputStream} where to write the compressed data
85 * is the specific {@code Deflater} that will be used to compress
88 * is the size to be used for the internal buffer.
90 public DeflaterOutputStream(OutputStream os, Deflater def, int bsize) {
91 this(os, def, bsize, false);
98 public DeflaterOutputStream(OutputStream os, boolean syncFlush) {
99 this(os, new Deflater(), BUF_SIZE, syncFlush);
106 public DeflaterOutputStream(OutputStream os, Deflater def, boolean syncFlush) {
107 this(os, def, BUF_SIZE, syncFlush);
114 public DeflaterOutputStream(OutputStream os, Deflater def, int bsize, boolean syncFlush) {
116 if (os == null || def == null) {
117 throw new NullPointerException();
120 throw new IllegalArgumentException();
123 this.syncFlush = syncFlush;
124 buf = new byte[bsize];
128 * Compress the data in the input buffer and write it to the underlying
131 * @throws IOException
132 * If an error occurs during deflation.
134 protected void deflate() throws IOException {
137 x = def.deflate(buf);
138 out.write(buf, 0, x);
139 } while (!def.needsInput());
143 * Writes any unwritten compressed data to the underlying stream, the closes
144 * all underlying streams. This stream can no longer be used after close()
147 * @throws IOException
148 * If an error occurs while closing the data compression
152 public void close() throws IOException {
153 if (!def.finished()) {
161 * Writes any unwritten data to the underlying stream. Does not close the
164 * @throws IOException
165 * If an error occurs.
167 public void finish() throws IOException {
173 while (!def.finished()) {
174 if (def.needsInput()) {
175 def.setInput(buf, 0, 0);
177 x = def.deflate(buf);
178 out.write(buf, 0, x);
184 public void write(int i) throws IOException {
185 byte[] b = new byte[1];
191 * Compresses {@code nbytes} of data from {@code buf} starting at
192 * {@code off} and writes it to the underlying stream.
195 * the buffer of data to compress.
197 * offset in buffer to extract data from.
199 * the number of bytes of data to read from the buffer.
200 * @throws IOException
201 * If an error occurs during writing.
204 public void write(byte[] buffer, int off, int nbytes) throws IOException {
206 throw new IOException("attempt to write after finish");
208 // avoid int overflow, check null buf
209 if (off <= buffer.length && nbytes >= 0 && off >= 0
210 && buffer.length - off >= nbytes) {
211 if (!def.needsInput()) {
212 throw new IOException();
214 def.setInput(buffer, off, nbytes);
217 throw new ArrayIndexOutOfBoundsException();
222 * Flushes the underlying stream. This flushes only the bytes that can be
223 * compressed at the highest level.
225 * <p>For deflater output streams constructed with Java 7's
226 * {@code syncFlush} parameter set to true (not yet available on Android),
227 * this first flushes all outstanding data so that it may be immediately
228 * read by its recipient. Doing so may degrade compression.
230 @Override public void flush() throws IOException {
232 int count = def.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH);
233 out.write(buf, 0, count);