jaroslav@694: /* jaroslav@694: * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. jaroslav@694: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@694: * jaroslav@694: * This code is free software; you can redistribute it and/or modify it jaroslav@694: * under the terms of the GNU General Public License version 2 only, as jaroslav@694: * published by the Free Software Foundation. Oracle designates this jaroslav@694: * particular file as subject to the "Classpath" exception as provided jaroslav@694: * by Oracle in the LICENSE file that accompanied this code. jaroslav@694: * jaroslav@694: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@694: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@694: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@694: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@694: * accompanied this code). jaroslav@694: * jaroslav@694: * You should have received a copy of the GNU General Public License version jaroslav@694: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@694: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@694: * jaroslav@694: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@694: * or visit www.oracle.com if you need additional information or have any jaroslav@694: * questions. jaroslav@694: */ jaroslav@609: jaroslav@609: package java.util.zip; jaroslav@609: jaroslav@609: /** jaroslav@609: * This class provides support for general purpose decompression using the jaroslav@609: * popular ZLIB compression library. The ZLIB compression library was jaroslav@609: * initially developed as part of the PNG graphics standard and is not jaroslav@609: * protected by patents. It is fully described in the specifications at jaroslav@609: * the java.util.zip jaroslav@609: * package description. jaroslav@609: * jaroslav@609: *

The following code fragment demonstrates a trivial compression jaroslav@609: * and decompression of a string using Deflater and jaroslav@609: * Inflater. jaroslav@609: * jaroslav@609: *

jaroslav@609:  * try {
jaroslav@609:  *     // Encode a String into bytes
jaroslav@609:  *     String inputString = "blahblahblah\u20AC\u20AC";
jaroslav@609:  *     byte[] input = inputString.getBytes("UTF-8");
jaroslav@609:  *
jaroslav@609:  *     // Compress the bytes
jaroslav@609:  *     byte[] output = new byte[100];
jaroslav@609:  *     Deflater compresser = new Deflater();
jaroslav@609:  *     compresser.setInput(input);
jaroslav@609:  *     compresser.finish();
jaroslav@609:  *     int compressedDataLength = compresser.deflate(output);
jaroslav@609:  *
jaroslav@609:  *     // Decompress the bytes
jaroslav@609:  *     Inflater decompresser = new Inflater();
jaroslav@609:  *     decompresser.setInput(output, 0, compressedDataLength);
jaroslav@609:  *     byte[] result = new byte[100];
jaroslav@609:  *     int resultLength = decompresser.inflate(result);
jaroslav@609:  *     decompresser.end();
jaroslav@609:  *
jaroslav@609:  *     // Decode the bytes into a String
jaroslav@609:  *     String outputString = new String(result, 0, resultLength, "UTF-8");
jaroslav@609:  * } catch(java.io.UnsupportedEncodingException ex) {
jaroslav@609:  *     // handle
jaroslav@609:  * } catch (java.util.zip.DataFormatException ex) {
jaroslav@609:  *     // handle
jaroslav@609:  * }
jaroslav@609:  * 
jaroslav@609: * jaroslav@609: * @see Deflater jaroslav@609: * @author David Connelly jaroslav@609: * jaroslav@609: */ jaroslav@694: public jaroslav@694: class Inflater { jaroslav@694: private final org.apidesign.bck2brwsr.emul.zip.Inflater impl; jaroslav@640: jaroslav@694: /** jaroslav@694: * Creates a new decompressor. If the parameter 'nowrap' is true then jaroslav@694: * the ZLIB header and checksum fields will not be used. This provides jaroslav@694: * compatibility with the compression format used by both GZIP and PKZIP. jaroslav@694: *

jaroslav@694: * Note: When using the 'nowrap' option it is also necessary to provide jaroslav@694: * an extra "dummy" byte as input. This is required by the ZLIB native jaroslav@694: * library in order to support certain optimizations. jaroslav@694: * jaroslav@694: * @param nowrap if true then support GZIP compatible compression jaroslav@640: */ jaroslav@694: public Inflater(boolean nowrap) { jaroslav@694: if (getClass() == org.apidesign.bck2brwsr.emul.zip.Inflater.class) { jaroslav@694: impl = null; jaroslav@694: } else { jaroslav@694: impl = new org.apidesign.bck2brwsr.emul.zip.Inflater(nowrap); jaroslav@687: } jaroslav@640: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Creates a new decompressor. jaroslav@694: */ jaroslav@694: public Inflater() { jaroslav@694: this(false); jaroslav@694: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Sets input data for decompression. Should be called whenever jaroslav@694: * needsInput() returns true indicating that more input data is jaroslav@694: * required. jaroslav@694: * @param b the input data bytes jaroslav@694: * @param off the start offset of the input data jaroslav@694: * @param len the length of the input data jaroslav@694: * @see Inflater#needsInput jaroslav@694: */ jaroslav@694: public void setInput(byte[] b, int off, int len) { jaroslav@694: impl.setInput(b, off, len); jaroslav@694: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Sets input data for decompression. Should be called whenever jaroslav@694: * needsInput() returns true indicating that more input data is jaroslav@694: * required. jaroslav@694: * @param b the input data bytes jaroslav@694: * @see Inflater#needsInput jaroslav@694: */ jaroslav@694: public void setInput(byte[] b) { jaroslav@694: impl.setInput(b); jaroslav@694: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Sets the preset dictionary to the given array of bytes. Should be jaroslav@694: * called when inflate() returns 0 and needsDictionary() returns true jaroslav@694: * indicating that a preset dictionary is required. The method getAdler() jaroslav@694: * can be used to get the Adler-32 value of the dictionary needed. jaroslav@694: * @param b the dictionary data bytes jaroslav@694: * @param off the start offset of the data jaroslav@694: * @param len the length of the data jaroslav@694: * @see Inflater#needsDictionary jaroslav@694: * @see Inflater#getAdler jaroslav@694: */ jaroslav@694: public void setDictionary(byte[] b, int off, int len) { jaroslav@694: impl.setDictionary(b, off, len); jaroslav@694: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Sets the preset dictionary to the given array of bytes. Should be jaroslav@694: * called when inflate() returns 0 and needsDictionary() returns true jaroslav@694: * indicating that a preset dictionary is required. The method getAdler() jaroslav@694: * can be used to get the Adler-32 value of the dictionary needed. jaroslav@694: * @param b the dictionary data bytes jaroslav@694: * @see Inflater#needsDictionary jaroslav@694: * @see Inflater#getAdler jaroslav@694: */ jaroslav@694: public void setDictionary(byte[] b) { jaroslav@694: impl.setDictionary(b); jaroslav@694: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Returns the total number of bytes remaining in the input buffer. jaroslav@694: * This can be used to find out what bytes still remain in the input jaroslav@694: * buffer after decompression has finished. jaroslav@694: * @return the total number of bytes remaining in the input buffer jaroslav@694: */ jaroslav@694: public int getRemaining() { jaroslav@694: return impl.getRemaining(); jaroslav@694: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Returns true if no data remains in the input buffer. This can jaroslav@694: * be used to determine if #setInput should be called in order jaroslav@694: * to provide more input. jaroslav@694: * @return true if no data remains in the input buffer jaroslav@694: */ jaroslav@694: public boolean needsInput() { jaroslav@694: return impl.needsInput(); jaroslav@694: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Returns true if a preset dictionary is needed for decompression. jaroslav@694: * @return true if a preset dictionary is needed for decompression jaroslav@694: * @see Inflater#setDictionary jaroslav@694: */ jaroslav@694: public boolean needsDictionary() { jaroslav@694: return impl.needsDictionary(); jaroslav@694: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Returns true if the end of the compressed data stream has been jaroslav@694: * reached. jaroslav@694: * @return true if the end of the compressed data stream has been jaroslav@694: * reached jaroslav@694: */ jaroslav@694: public boolean finished() { jaroslav@694: return impl.finished(); jaroslav@694: } jaroslav@694: jaroslav@694: /** jaroslav@694: * Uncompresses bytes into specified buffer. Returns actual number jaroslav@694: * of bytes uncompressed. A return value of 0 indicates that jaroslav@694: * needsInput() or needsDictionary() should be called in order to jaroslav@694: * determine if more input data or a preset dictionary is required. jaroslav@694: * In the latter case, getAdler() can be used to get the Adler-32 jaroslav@694: * value of the dictionary required. jaroslav@694: * @param b the buffer for the uncompressed data jaroslav@694: * @param off the start offset of the data jaroslav@694: * @param len the maximum number of uncompressed bytes jaroslav@694: * @return the actual number of uncompressed bytes jaroslav@694: * @exception DataFormatException if the compressed data format is invalid jaroslav@694: * @see Inflater#needsInput jaroslav@694: * @see Inflater#needsDictionary jaroslav@694: */ jaroslav@694: public int inflate(byte[] b, int off, int len) jaroslav@694: throws DataFormatException jaroslav@640: { jaroslav@694: return impl.inflate(b, off, len); jaroslav@694: } jaroslav@640: jaroslav@694: /** jaroslav@694: * Uncompresses bytes into specified buffer. Returns actual number jaroslav@694: * of bytes uncompressed. A return value of 0 indicates that jaroslav@694: * needsInput() or needsDictionary() should be called in order to jaroslav@694: * determine if more input data or a preset dictionary is required. jaroslav@694: * In the latter case, getAdler() can be used to get the Adler-32 jaroslav@694: * value of the dictionary required. jaroslav@694: * @param b the buffer for the uncompressed data jaroslav@694: * @return the actual number of uncompressed bytes jaroslav@694: * @exception DataFormatException if the compressed data format is invalid jaroslav@694: * @see Inflater#needsInput jaroslav@694: * @see Inflater#needsDictionary jaroslav@694: */ jaroslav@694: public int inflate(byte[] b) throws DataFormatException { jaroslav@694: return impl.inflate(b); jaroslav@694: } jaroslav@640: jaroslav@694: /** jaroslav@694: * Returns the ADLER-32 value of the uncompressed data. jaroslav@694: * @return the ADLER-32 value of the uncompressed data jaroslav@694: */ jaroslav@694: public int getAdler() { jaroslav@694: return impl.getAdler(); jaroslav@694: } jaroslav@640: jaroslav@694: /** jaroslav@694: * Returns the total number of compressed bytes input so far. jaroslav@694: * jaroslav@694: *

Since the number of bytes may be greater than jaroslav@694: * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now jaroslav@694: * the preferred means of obtaining this information.

jaroslav@694: * jaroslav@694: * @return the total number of compressed bytes input so far jaroslav@694: */ jaroslav@694: public int getTotalIn() { jaroslav@694: return impl.getTotalIn(); jaroslav@694: } jaroslav@640: jaroslav@694: /** jaroslav@694: * Returns the total number of compressed bytes input so far.

jaroslav@694: * jaroslav@694: * @return the total (non-negative) number of compressed bytes input so far jaroslav@694: * @since 1.5 jaroslav@694: */ jaroslav@694: public long getBytesRead() { jaroslav@694: return impl.getBytesRead(); jaroslav@694: } jaroslav@640: jaroslav@694: /** jaroslav@694: * Returns the total number of uncompressed bytes output so far. jaroslav@694: * jaroslav@694: *

Since the number of bytes may be greater than jaroslav@694: * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now jaroslav@694: * the preferred means of obtaining this information.

jaroslav@694: * jaroslav@694: * @return the total number of uncompressed bytes output so far jaroslav@694: */ jaroslav@694: public int getTotalOut() { jaroslav@694: return impl.getTotalOut(); jaroslav@694: } jaroslav@640: jaroslav@694: /** jaroslav@694: * Returns the total number of uncompressed bytes output so far.

jaroslav@694: * jaroslav@694: * @return the total (non-negative) number of uncompressed bytes output so far jaroslav@694: * @since 1.5 jaroslav@694: */ jaroslav@694: public long getBytesWritten() { jaroslav@694: return impl.getBytesWritten(); jaroslav@694: } jaroslav@640: jaroslav@694: /** jaroslav@694: * Resets inflater so that a new set of input data can be processed. jaroslav@694: */ jaroslav@694: public void reset() { jaroslav@694: impl.reset(); jaroslav@694: } jaroslav@640: jaroslav@694: /** jaroslav@694: * Closes the decompressor and discards any unprocessed input. jaroslav@694: * This method should be called when the decompressor is no longer jaroslav@694: * being used, but will also be called automatically by the finalize() jaroslav@694: * method. Once this method is called, the behavior of the Inflater jaroslav@694: * object is undefined. jaroslav@694: */ jaroslav@694: public void end() { jaroslav@694: impl.end(); jaroslav@694: } jaroslav@640: jaroslav@694: /** jaroslav@694: * Closes the decompressor when garbage is collected. jaroslav@694: */ jaroslav@694: protected void finalize() { jaroslav@694: end(); jaroslav@640: } jaroslav@609: }