40
40
* @since 1.1
41
41
*/
42
42
public class DeflaterOutputStream extends FilterOutputStream {
43
+
44
+ /*
45
+ * The default size of the output buffer
46
+ */
47
+ static final int DEFAULT_BUF_SIZE = 512 ;
48
+
49
+ /*
50
+ * When calling Deflater.deflate() with Deflater.SYNC_FLUSH or Deflater.FULL_FLUSH,
51
+ * the callers are expected to ensure that the size of the buffer is greater than 6.
52
+ * This expectation comes from the underlying zlib library which in its zlib.h
53
+ * states:
54
+ * "If deflate returns with avail_out == 0, this function must be called again
55
+ * with the same value of the flush parameter and more output space (updated
56
+ * avail_out), until the flush is complete (deflate returns with non-zero
57
+ * avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
58
+ * avail_out is greater than six when the flush marker begins, in order to avoid
59
+ * repeated flush markers upon calling deflate() again when avail_out == 0."
60
+ */
61
+ private static final int SYNC_FLUSH_MIN_BUF_SIZE = 7 ;
62
+
43
63
/**
44
64
* Compressor for this stream.
45
65
*/
@@ -123,7 +143,7 @@ public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
123
143
public DeflaterOutputStream (OutputStream out ,
124
144
Deflater def ,
125
145
boolean syncFlush ) {
126
- this (out , def , 512 , syncFlush );
146
+ this (out , def , DEFAULT_BUF_SIZE , syncFlush );
127
147
}
128
148
129
149
@@ -138,7 +158,7 @@ public DeflaterOutputStream(OutputStream out,
138
158
* @param def the compressor ("deflater")
139
159
*/
140
160
public DeflaterOutputStream (OutputStream out , Deflater def ) {
141
- this (out , def , 512 , false );
161
+ this (out , def , DEFAULT_BUF_SIZE , false );
142
162
}
143
163
144
164
boolean usesDefaultDeflater = false ;
@@ -158,7 +178,7 @@ public DeflaterOutputStream(OutputStream out, Deflater def) {
158
178
* @since 1.7
159
179
*/
160
180
public DeflaterOutputStream (OutputStream out , boolean syncFlush ) {
161
- this (out , out != null ? new Deflater () : null , 512 , syncFlush );
181
+ this (out , out != null ? new Deflater () : null , DEFAULT_BUF_SIZE , syncFlush );
162
182
usesDefaultDeflater = true ;
163
183
}
164
184
@@ -181,6 +201,7 @@ public DeflaterOutputStream(OutputStream out) {
181
201
* @param b the byte to be written
182
202
* @throws IOException if an I/O error has occurred
183
203
*/
204
+ @ Override
184
205
public void write (int b ) throws IOException {
185
206
byte [] buf = new byte [1 ];
186
207
buf [0 ] = (byte )(b & 0xff );
@@ -195,6 +216,7 @@ public void write(int b) throws IOException {
195
216
* @param len the length of the data
196
217
* @throws IOException if an I/O error has occurred
197
218
*/
219
+ @ Override
198
220
public void write (byte [] b , int off , int len ) throws IOException {
199
221
if (def .finished ()) {
200
222
throw new IOException ("write beyond end of stream" );
@@ -238,6 +260,7 @@ public void finish() throws IOException {
238
260
* underlying stream.
239
261
* @throws IOException if an I/O error has occurred
240
262
*/
263
+ @ Override
241
264
public void close () throws IOException {
242
265
if (!closed ) {
243
266
try {
@@ -277,13 +300,20 @@ protected void deflate() throws IOException {
277
300
*
278
301
* @since 1.7
279
302
*/
303
+ @ Override
280
304
public void flush () throws IOException {
281
305
if (syncFlush && !def .finished ()) {
282
306
int len = 0 ;
283
- while ((len = def .deflate (buf , 0 , buf .length , Deflater .SYNC_FLUSH )) > 0 )
284
- {
285
- out .write (buf , 0 , len );
286
- if (len < buf .length )
307
+ // For SYNC_FLUSH, the Deflater.deflate() expects the callers
308
+ // to use a buffer whose length is greater than 6 to avoid
309
+ // flush marker (5 bytes) being repeatedly output to the output buffer
310
+ // every time it is invoked.
311
+ final byte [] flushBuf = buf .length < SYNC_FLUSH_MIN_BUF_SIZE
312
+ ? new byte [DEFAULT_BUF_SIZE ]
313
+ : buf ;
314
+ while ((len = def .deflate (flushBuf , 0 , flushBuf .length , Deflater .SYNC_FLUSH )) > 0 ) {
315
+ out .write (flushBuf , 0 , len );
316
+ if (len < flushBuf .length )
287
317
break ;
288
318
}
289
319
}
0 commit comments