49 * compresser.setInput(input);
50 * compresser.finish();
51 * int compressedDataLength = compresser.deflate(output);
52 *
53 * // Decompress the bytes
54 * Inflater decompresser = new Inflater();
55 * decompresser.setInput(output, 0, compressedDataLength);
56 * byte[] result = new byte[100];
57 * int resultLength = decompresser.inflate(result);
58 * decompresser.end();
59 *
60 * // Decode the bytes into a String
61 * String outputString = new String(result, 0, resultLength, "UTF-8");
62 * } catch(java.io.UnsupportedEncodingException ex) {
63 * // handle
64 * } catch (java.util.zip.DataFormatException ex) {
65 * // handle
66 * }
67 * </pre></blockquote>
68 *
69 * @see Deflater
70 * @author David Connelly
71 * @since 1.1
72 *
73 */
74 public
75 class Inflater {
76
77 private final ZStreamRef zsRef;
78 private byte[] buf = defaultBuf;
79 private int off, len;
80 private boolean finished;
81 private boolean needDict;
82 private long bytesRead;
83 private long bytesWritten;
84
85 private static final byte[] defaultBuf = new byte[0];
86
87 static {
88 ZipUtils.loadLibrary();
89 initIDs();
90 }
91
92 /**
93 * Creates a new decompressor. If the parameter 'nowrap' is true then
94 * the ZLIB header and checksum fields will not be used. This provides
95 * compatibility with the compression format used by both GZIP and PKZIP.
96 * <p>
97 * Note: When using the 'nowrap' option it is also necessary to provide
98 * an extra "dummy" byte as input. This is required by the ZLIB native
99 * library in order to support certain optimizations.
100 *
101 * @param nowrap if true then support GZIP compatible compression
102 */
103 public Inflater(boolean nowrap) {
104 zsRef = new ZStreamRef(init(nowrap));
105 }
106
107 /**
108 * Creates a new decompressor.
109 */
110 public Inflater() {
111 this(false);
112 }
113
114 /**
115 * Sets input data for decompression. Should be called whenever
116 * needsInput() returns true indicating that more input data is
117 * required.
118 * @param b the input data bytes
119 * @param off the start offset of the input data
120 * @param len the length of the input data
121 * @see Inflater#needsInput
122 */
123 public void setInput(byte[] b, int off, int len) {
124 if (b == null) {
344 }
345 }
346
347 /**
348 * Resets inflater so that a new set of input data can be processed.
349 */
350 public void reset() {
351 synchronized (zsRef) {
352 ensureOpen();
353 reset(zsRef.address());
354 buf = defaultBuf;
355 finished = false;
356 needDict = false;
357 off = len = 0;
358 bytesRead = bytesWritten = 0;
359 }
360 }
361
362 /**
363 * Closes the decompressor and discards any unprocessed input.
364 * This method should be called when the decompressor is no longer
365 * being used, but will also be called automatically by the finalize()
366 * method. Once this method is called, the behavior of the Inflater
367 * object is undefined.
368 */
369 public void end() {
370 synchronized (zsRef) {
371 long addr = zsRef.address();
372 zsRef.clear();
373 if (addr != 0) {
374 end(addr);
375 buf = null;
376 }
377 }
378 }
379
380 /**
381 * Closes the decompressor when garbage is collected.
382 *
383 * @deprecated The {@code finalize} method has been deprecated.
384 * Subclasses that override {@code finalize} in order to perform cleanup
385 * should be modified to use alternative cleanup mechanisms and
386 * to remove the overriding {@code finalize} method.
387 * When overriding the {@code finalize} method, its implementation must explicitly
388 * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
389 * See the specification for {@link Object#finalize()} for further
390 * information about migration options.
391 */
392 @Deprecated(since="9")
393 protected void finalize() {
394 end();
395 }
396
397 private void ensureOpen () {
398 assert Thread.holdsLock(zsRef);
399 if (zsRef.address() == 0)
400 throw new NullPointerException("Inflater has been closed");
401 }
402
403 boolean ended() {
404 synchronized (zsRef) {
405 return zsRef.address() == 0;
406 }
407 }
408
409 private static native void initIDs();
410 private static native long init(boolean nowrap);
411 private static native void setDictionary(long addr, byte[] b, int off,
412 int len);
413 private native int inflateBytes(long addr, byte[] b, int off, int len)
414 throws DataFormatException;
|
49 * compresser.setInput(input);
50 * compresser.finish();
51 * int compressedDataLength = compresser.deflate(output);
52 *
53 * // Decompress the bytes
54 * Inflater decompresser = new Inflater();
55 * decompresser.setInput(output, 0, compressedDataLength);
56 * byte[] result = new byte[100];
57 * int resultLength = decompresser.inflate(result);
58 * decompresser.end();
59 *
60 * // Decode the bytes into a String
61 * String outputString = new String(result, 0, resultLength, "UTF-8");
62 * } catch(java.io.UnsupportedEncodingException ex) {
63 * // handle
64 * } catch (java.util.zip.DataFormatException ex) {
65 * // handle
66 * }
67 * </pre></blockquote>
68 *
69 * <p>
70 * @apiNote
71 * In earlier versions the {@link Object#finalize} method was overridden and
72 * specified to call the {@code end} method to close the {@code inflater} and
73 * release the resource when the instance becomes unreachable.
74 * The {@code finalize} method is no longer defined. The recommended cleanup
75 * for decompressor is to explicitly call {@code end} method when it is no
76 * longer in use.
77 *
78 * @implNote
79 * The resource of the decompressor will be released when the instance becomes
80 * phantom-reachable, if the {@code end} is not invoked explicitly.
81 * <p>
82 *
83 * @see Deflater
84 * @author David Connelly
85 * @since 1.1
86 *
87 */
88 public
89 class Inflater {
90
91 private final ZStreamRef zsRef;
92 private byte[] buf = defaultBuf;
93 private int off, len;
94 private boolean finished;
95 private boolean needDict;
96 private long bytesRead;
97 private long bytesWritten;
98
99 private static final byte[] defaultBuf = new byte[0];
100
101 static {
102 ZipUtils.loadLibrary();
103 initIDs();
104 }
105
106 /**
107 * Creates a new decompressor. If the parameter 'nowrap' is true then
108 * the ZLIB header and checksum fields will not be used. This provides
109 * compatibility with the compression format used by both GZIP and PKZIP.
110 * <p>
111 * Note: When using the 'nowrap' option it is also necessary to provide
112 * an extra "dummy" byte as input. This is required by the ZLIB native
113 * library in order to support certain optimizations.
114 *
115 * @param nowrap if true then support GZIP compatible compression
116 */
117 public Inflater(boolean nowrap) {
118 this.zsRef = new ZStreamRef(this, () -> init(nowrap), Inflater::end);
119 }
120
121 /**
122 * Creates a new decompressor.
123 */
124 public Inflater() {
125 this(false);
126 }
127
128 /**
129 * Sets input data for decompression. Should be called whenever
130 * needsInput() returns true indicating that more input data is
131 * required.
132 * @param b the input data bytes
133 * @param off the start offset of the input data
134 * @param len the length of the input data
135 * @see Inflater#needsInput
136 */
137 public void setInput(byte[] b, int off, int len) {
138 if (b == null) {
358 }
359 }
360
361 /**
362 * Resets inflater so that a new set of input data can be processed.
363 */
364 public void reset() {
365 synchronized (zsRef) {
366 ensureOpen();
367 reset(zsRef.address());
368 buf = defaultBuf;
369 finished = false;
370 needDict = false;
371 off = len = 0;
372 bytesRead = bytesWritten = 0;
373 }
374 }
375
376 /**
377 * Closes the decompressor and discards any unprocessed input.
378 *
379 * This method should be called when the decompressor is no longer
380 * being used. Once this method is called, the behavior of the
381 * Inflater object is undefined.
382 */
383 public void end() {
384 synchronized (zsRef) {
385 zsRef.clean();
386 buf = null;
387 }
388 }
389
390 private void ensureOpen () {
391 assert Thread.holdsLock(zsRef);
392 if (zsRef.address() == 0)
393 throw new NullPointerException("Inflater has been closed");
394 }
395
396 boolean ended() {
397 synchronized (zsRef) {
398 return zsRef.address() == 0;
399 }
400 }
401
402 private static native void initIDs();
403 private static native long init(boolean nowrap);
404 private static native void setDictionary(long addr, byte[] b, int off,
405 int len);
406 private native int inflateBytes(long addr, byte[] b, int off, int len)
407 throws DataFormatException;
|