< prev index next >

src/java.base/share/classes/java/util/zip/Deflater.java

Print this page




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.util.zip;
  27 





  28 /**
  29  * This class provides support for general purpose compression using the
  30  * popular ZLIB compression library. The ZLIB compression library was
  31  * initially developed as part of the PNG graphics standard and is not
  32  * protected by patents. It is fully described in the specifications at
  33  * the <a href="package-summary.html#package.description">java.util.zip
  34  * package description</a>.
  35  *
  36  * <p>The following code fragment demonstrates a trivial compression
  37  * and decompression of a string using {@code Deflater} and
  38  * {@code Inflater}.
  39  *
  40  * <blockquote><pre>
  41  * try {
  42  *     // Encode a String into bytes
  43  *     String inputString = "blahblahblah";
  44  *     byte[] input = inputString.getBytes("UTF-8");
  45  *
  46  *     // Compress the bytes
  47  *     byte[] output = new byte[100];


  50  *     compresser.finish();
  51  *     int compressedDataLength = compresser.deflate(output);
  52  *     compresser.end();
  53  *
  54  *     // Decompress the bytes
  55  *     Inflater decompresser = new Inflater();
  56  *     decompresser.setInput(output, 0, compressedDataLength);
  57  *     byte[] result = new byte[100];
  58  *     int resultLength = decompresser.inflate(result);
  59  *     decompresser.end();
  60  *
  61  *     // Decode the bytes into a String
  62  *     String outputString = new String(result, 0, resultLength, "UTF-8");
  63  * } catch(java.io.UnsupportedEncodingException ex) {
  64  *     // handle
  65  * } catch (java.util.zip.DataFormatException ex) {
  66  *     // handle
  67  * }
  68  * </pre></blockquote>
  69  *














  70  * @see         Inflater
  71  * @author      David Connelly
  72  * @since 1.1
  73  */
  74 public
  75 class Deflater {
  76 
  77     private final ZStreamRef zsRef;
  78     private byte[] buf = new byte[0];
  79     private int off, len;
  80     private int level, strategy;
  81     private boolean setParams;
  82     private boolean finish, finished;
  83     private long bytesRead;
  84     private long bytesWritten;
  85 
  86     /**
  87      * Compression method for the deflate algorithm (the only one currently
  88      * supported).
  89      */
  90     public static final int DEFLATED = 8;
  91 
  92     /**
  93      * Compression level for no compression.
  94      */
  95     public static final int NO_COMPRESSION = 0;
  96 
  97     /**


 152      * @since 1.7
 153      */
 154     public static final int FULL_FLUSH = 3;
 155 
 156     static {
 157         ZipUtils.loadLibrary();
 158         initIDs();
 159     }
 160 
 161     /**
 162      * Creates a new compressor using the specified compression level.
 163      * If 'nowrap' is true then the ZLIB header and checksum fields will
 164      * not be used in order to support the compression format used in
 165      * both GZIP and PKZIP.
 166      * @param level the compression level (0-9)
 167      * @param nowrap if true then use GZIP compatible compression
 168      */
 169     public Deflater(int level, boolean nowrap) {
 170         this.level = level;
 171         this.strategy = DEFAULT_STRATEGY;
 172         this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));




 173     }
 174 
 175     /**
 176      * Creates a new compressor using the specified compression level.
 177      * Compressed data will be generated in ZLIB format.
 178      * @param level the compression level (0-9)
 179      */
 180     public Deflater(int level) {
 181         this(level, false);
 182     }
 183 
 184     /**
 185      * Creates a new compressor with the default compression level.
 186      * Compressed data will be generated in ZLIB format.
 187      */
 188     public Deflater() {
 189         this(DEFAULT_COMPRESSION, false);
 190     }
 191 
 192     /**


 225      * Sets preset dictionary for compression. A preset dictionary is used
 226      * when the history buffer can be predetermined. When the data is later
 227      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
 228      * in order to get the Adler-32 value of the dictionary required for
 229      * decompression.
 230      * @param b the dictionary data bytes
 231      * @param off the start offset of the data
 232      * @param len the length of the data
 233      * @see Inflater#inflate
 234      * @see Inflater#getAdler
 235      */
 236     public void setDictionary(byte[] b, int off, int len) {
 237         if (b == null) {
 238             throw new NullPointerException();
 239         }
 240         if (off < 0 || len < 0 || off > b.length - len) {
 241             throw new ArrayIndexOutOfBoundsException();
 242         }
 243         synchronized (zsRef) {
 244             ensureOpen();
 245             setDictionary(zsRef.address(), b, off, len);

 246         }
 247     }
 248 
 249     /**
 250      * Sets preset dictionary for compression. A preset dictionary is used
 251      * when the history buffer can be predetermined. When the data is later
 252      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
 253      * in order to get the Adler-32 value of the dictionary required for
 254      * decompression.
 255      * @param b the dictionary data bytes
 256      * @see Inflater#inflate
 257      * @see Inflater#getAdler
 258      */
 259     public void setDictionary(byte[] b) {
 260         setDictionary(b, 0, b.length);
 261     }
 262 
 263     /**
 264      * Sets the compression strategy to the specified value.
 265      *


 428      * @param len the maximum number of bytes of compressed data
 429      * @param flush the compression flush mode
 430      * @return the actual number of bytes of compressed data written to
 431      *         the output buffer
 432      *
 433      * @throws IllegalArgumentException if the flush mode is invalid
 434      * @since 1.7
 435      */
 436     public int deflate(byte[] b, int off, int len, int flush) {
 437         if (b == null) {
 438             throw new NullPointerException();
 439         }
 440         if (off < 0 || len < 0 || off > b.length - len) {
 441             throw new ArrayIndexOutOfBoundsException();
 442         }
 443         synchronized (zsRef) {
 444             ensureOpen();
 445             if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
 446                 flush == FULL_FLUSH) {
 447                 int thisLen = this.len;
 448                 int n = deflateBytes(zsRef.address(), b, off, len, flush);

 449                 bytesWritten += n;
 450                 bytesRead += (thisLen - this.len);
 451                 return n;
 452             }
 453             throw new IllegalArgumentException();
 454         }
 455     }
 456 
 457     /**
 458      * Returns the ADLER-32 value of the uncompressed data.
 459      * @return the ADLER-32 value of the uncompressed data
 460      */
 461     public int getAdler() {
 462         synchronized (zsRef) {
 463             ensureOpen();
 464             return getAdler(zsRef.address());


 465         }
 466     }
 467 
 468     /**
 469      * Returns the total number of uncompressed bytes input so far.
 470      *
 471      * <p>Since the number of bytes may be greater than
 472      * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
 473      * the preferred means of obtaining this information.</p>
 474      *
 475      * @return the total number of uncompressed bytes input so far
 476      */
 477     public int getTotalIn() {
 478         return (int) getBytesRead();
 479     }
 480 
 481     /**
 482      * Returns the total number of uncompressed bytes input so far.
 483      *
 484      * @return the total (non-negative) number of uncompressed bytes input so far


 507     /**
 508      * Returns the total number of compressed bytes output so far.
 509      *
 510      * @return the total (non-negative) number of compressed bytes output so far
 511      * @since 1.5
 512      */
 513     public long getBytesWritten() {
 514         synchronized (zsRef) {
 515             ensureOpen();
 516             return bytesWritten;
 517         }
 518     }
 519 
 520     /**
 521      * Resets deflater so that a new set of input data can be processed.
 522      * Keeps current compression level and strategy settings.
 523      */
 524     public void reset() {
 525         synchronized (zsRef) {
 526             ensureOpen();
 527             reset(zsRef.address());

 528             finish = false;
 529             finished = false;
 530             off = len = 0;
 531             bytesRead = bytesWritten = 0;
 532         }
 533     }
 534 
 535     /**
 536      * Closes the compressor and discards any unprocessed input.

 537      * This method should be called when the compressor is no longer
 538      * being used, but will also be called automatically by the
 539      * finalize() method. Once this method is called, the behavior
 540      * of the Deflater object is undefined.
 541      */
 542     public void end() {
 543         synchronized (zsRef) {
 544             long addr = zsRef.address();
 545             zsRef.clear();
 546             if (addr != 0) {
 547                 end(addr);
 548                 buf = null;
 549             }
 550         }
 551     }
 552 
 553     /**
 554      * Closes the compressor when garbage is collected.
 555      *
 556      * @deprecated The {@code finalize} method has been deprecated.
 557      *     Subclasses that override {@code finalize} in order to perform cleanup
 558      *     should be modified to use alternative cleanup mechanisms and
 559      *     to remove the overriding {@code finalize} method.
 560      *     When overriding the {@code finalize} method, its implementation must explicitly
 561      *     ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
 562      *     See the specification for {@link Object#finalize()} for further
 563      *     information about migration options.
 564      */
 565     @Deprecated(since="9")
 566     protected void finalize() {
 567         end();
 568     }
 569 
 570     private void ensureOpen() {
 571         assert Thread.holdsLock(zsRef);
 572         if (zsRef.address() == 0)


 573             throw new NullPointerException("Deflater has been closed");

 574     }
 575 
 576     private static native void initIDs();
 577     private static native long init(int level, int strategy, boolean nowrap);
 578     private static native void setDictionary(long addr, byte[] b, int off, int len);
 579     private native int deflateBytes(long addr, byte[] b, int off, int len,
 580                                     int flush);
 581     private static native int getAdler(long addr);
 582     private static native void reset(long addr);
 583     private static native void end(long addr);
 584 }


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.util.zip;
  27 
  28 import jdk.internal.ref.CleanerFactory;
  29 
  30 import java.lang.ref.Cleaner;
  31 import java.lang.ref.Reference;
  32 
  33 /**
  34  * This class provides support for general purpose compression using the
  35  * popular ZLIB compression library. The ZLIB compression library was
  36  * initially developed as part of the PNG graphics standard and is not
  37  * protected by patents. It is fully described in the specifications at
  38  * the <a href="package-summary.html#package.description">java.util.zip
  39  * package description</a>.
  40  *
  41  * <p>The following code fragment demonstrates a trivial compression
  42  * and decompression of a string using {@code Deflater} and
  43  * {@code Inflater}.
  44  *
  45  * <blockquote><pre>
  46  * try {
  47  *     // Encode a String into bytes
  48  *     String inputString = "blahblahblah";
  49  *     byte[] input = inputString.getBytes("UTF-8");
  50  *
  51  *     // Compress the bytes
  52  *     byte[] output = new byte[100];


  55  *     compresser.finish();
  56  *     int compressedDataLength = compresser.deflate(output);
  57  *     compresser.end();
  58  *
  59  *     // Decompress the bytes
  60  *     Inflater decompresser = new Inflater();
  61  *     decompresser.setInput(output, 0, compressedDataLength);
  62  *     byte[] result = new byte[100];
  63  *     int resultLength = decompresser.inflate(result);
  64  *     decompresser.end();
  65  *
  66  *     // Decode the bytes into a String
  67  *     String outputString = new String(result, 0, resultLength, "UTF-8");
  68  * } catch(java.io.UnsupportedEncodingException ex) {
  69  *     // handle
  70  * } catch (java.util.zip.DataFormatException ex) {
  71  *     // handle
  72  * }
  73  * </pre></blockquote>
  74  *
  75  * <p>
  76  * @apiNote
  77  * In earlier versions the {@link Object#finalize} method was overridden and
  78  * specified to call the {@code end} method to close the {@code deflater} and
  79  * release the resource when the instance becomes unreachable.
  80  * The {@code finalize} method is no longer defined. The recommended cleanup
  81  * for compressor is to explicitly call {@code end} method when it is no
  82  * longer in use.
  83  *
  84  * @implNote
  85  * The resource of the compressor will be released when the instance becomes
  86  * phantom-reachable, if the {@code end} is not invoked explicitly.
  87  * <p>
  88  *
  89  * @see         Inflater
  90  * @author      David Connelly
  91  * @since 1.1
  92  */
  93 public
  94 class Deflater {
  95 
  96     private final Cleaner.LongCleanableResource zsRef;
  97     private byte[] buf = new byte[0];
  98     private int off, len;
  99     private int level, strategy;
 100     private boolean setParams;
 101     private boolean finish, finished;
 102     private long bytesRead;
 103     private long bytesWritten;
 104 
 105     /**
 106      * Compression method for the deflate algorithm (the only one currently
 107      * supported).
 108      */
 109     public static final int DEFLATED = 8;
 110 
 111     /**
 112      * Compression level for no compression.
 113      */
 114     public static final int NO_COMPRESSION = 0;
 115 
 116     /**


 171      * @since 1.7
 172      */
 173     public static final int FULL_FLUSH = 3;
 174 
 175     static {
 176         ZipUtils.loadLibrary();
 177         initIDs();
 178     }
 179 
 180     /**
 181      * Creates a new compressor using the specified compression level.
 182      * If 'nowrap' is true then the ZLIB header and checksum fields will
 183      * not be used in order to support the compression format used in
 184      * both GZIP and PKZIP.
 185      * @param level the compression level (0-9)
 186      * @param nowrap if true then use GZIP compatible compression
 187      */
 188     public Deflater(int level, boolean nowrap) {
 189         this.level = level;
 190         this.strategy = DEFAULT_STRATEGY;
 191         this.zsRef = CleanerFactory
 192             .cleaner()
 193             .createLongResource(this,
 194                                 () -> init(level, DEFAULT_STRATEGY, nowrap),
 195                                 Deflater::end);
 196     }
 197 
 198     /**
 199      * Creates a new compressor using the specified compression level.
 200      * Compressed data will be generated in ZLIB format.
 201      * @param level the compression level (0-9)
 202      */
 203     public Deflater(int level) {
 204         this(level, false);
 205     }
 206 
 207     /**
 208      * Creates a new compressor with the default compression level.
 209      * Compressed data will be generated in ZLIB format.
 210      */
 211     public Deflater() {
 212         this(DEFAULT_COMPRESSION, false);
 213     }
 214 
 215     /**


 248      * Sets preset dictionary for compression. A preset dictionary is used
 249      * when the history buffer can be predetermined. When the data is later
 250      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
 251      * in order to get the Adler-32 value of the dictionary required for
 252      * decompression.
 253      * @param b the dictionary data bytes
 254      * @param off the start offset of the data
 255      * @param len the length of the data
 256      * @see Inflater#inflate
 257      * @see Inflater#getAdler
 258      */
 259     public void setDictionary(byte[] b, int off, int len) {
 260         if (b == null) {
 261             throw new NullPointerException();
 262         }
 263         if (off < 0 || len < 0 || off > b.length - len) {
 264             throw new ArrayIndexOutOfBoundsException();
 265         }
 266         synchronized (zsRef) {
 267             ensureOpen();
 268             setDictionary(zsRef.value(), b, off, len);
 269             Reference.reachabilityFence(this);
 270         }
 271     }
 272 
 273     /**
 274      * Sets preset dictionary for compression. A preset dictionary is used
 275      * when the history buffer can be predetermined. When the data is later
 276      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
 277      * in order to get the Adler-32 value of the dictionary required for
 278      * decompression.
 279      * @param b the dictionary data bytes
 280      * @see Inflater#inflate
 281      * @see Inflater#getAdler
 282      */
 283     public void setDictionary(byte[] b) {
 284         setDictionary(b, 0, b.length);
 285     }
 286 
 287     /**
 288      * Sets the compression strategy to the specified value.
 289      *


 452      * @param len the maximum number of bytes of compressed data
 453      * @param flush the compression flush mode
 454      * @return the actual number of bytes of compressed data written to
 455      *         the output buffer
 456      *
 457      * @throws IllegalArgumentException if the flush mode is invalid
 458      * @since 1.7
 459      */
 460     public int deflate(byte[] b, int off, int len, int flush) {
 461         if (b == null) {
 462             throw new NullPointerException();
 463         }
 464         if (off < 0 || len < 0 || off > b.length - len) {
 465             throw new ArrayIndexOutOfBoundsException();
 466         }
 467         synchronized (zsRef) {
 468             ensureOpen();
 469             if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
 470                 flush == FULL_FLUSH) {
 471                 int thisLen = this.len;
 472                 int n = deflateBytes(zsRef.value(), b, off, len, flush);
 473                 Reference.reachabilityFence(this);
 474                 bytesWritten += n;
 475                 bytesRead += (thisLen - this.len);
 476                 return n;
 477             }
 478             throw new IllegalArgumentException();
 479         }
 480     }
 481 
 482     /**
 483      * Returns the ADLER-32 value of the uncompressed data.
 484      * @return the ADLER-32 value of the uncompressed data
 485      */
 486     public int getAdler() {
 487         synchronized (zsRef) {
 488             ensureOpen();
 489             int adler = getAdler(zsRef.value());
 490             Reference.reachabilityFence(this);
 491             return adler;
 492         }
 493     }
 494 
 495     /**
 496      * Returns the total number of uncompressed bytes input so far.
 497      *
 498      * <p>Since the number of bytes may be greater than
 499      * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
 500      * the preferred means of obtaining this information.</p>
 501      *
 502      * @return the total number of uncompressed bytes input so far
 503      */
 504     public int getTotalIn() {
 505         return (int) getBytesRead();
 506     }
 507 
 508     /**
 509      * Returns the total number of uncompressed bytes input so far.
 510      *
 511      * @return the total (non-negative) number of uncompressed bytes input so far


 534     /**
 535      * Returns the total number of compressed bytes output so far.
 536      *
 537      * @return the total (non-negative) number of compressed bytes output so far
 538      * @since 1.5
 539      */
 540     public long getBytesWritten() {
 541         synchronized (zsRef) {
 542             ensureOpen();
 543             return bytesWritten;
 544         }
 545     }
 546 
 547     /**
 548      * Resets deflater so that a new set of input data can be processed.
 549      * Keeps current compression level and strategy settings.
 550      */
 551     public void reset() {
 552         synchronized (zsRef) {
 553             ensureOpen();
 554             reset(zsRef.value());
 555             Reference.reachabilityFence(this);
 556             finish = false;
 557             finished = false;
 558             off = len = 0;
 559             bytesRead = bytesWritten = 0;
 560         }
 561     }
 562 
 563     /**
 564      * Closes the compressor and discards any unprocessed input.
 565      *
 566      * This method should be called when the compressor is no longer
 567      * being used. Once this method is called, the behavior of the
 568      * Deflater object is undefined.

 569      */
 570     public void end() {
 571         synchronized (zsRef) {
 572             zsRef.clean();



 573             buf = null;
 574         }
 575     }


















 576 
 577     private void ensureOpen() {
 578         assert Thread.holdsLock(zsRef);
 579         try {
 580             zsRef.value();
 581         } catch (IllegalStateException e) {
 582             throw new NullPointerException("Deflater has been closed");
 583         }
 584     }
 585 
 586     private static native void initIDs();
 587     private static native long init(int level, int strategy, boolean nowrap);
 588     private static native void setDictionary(long addr, byte[] b, int off, int len);
 589     private native int deflateBytes(long addr, byte[] b, int off, int len,
 590                                     int flush);
 591     private static native int getAdler(long addr);
 592     private static native void reset(long addr);
 593     private static native void end(long addr);
 594 }
< prev index next >