Question

I would like to be able to flush any pending data in a DeflaterOutputStream and read it in a InflaterInputStream. However, it appears that flush(), doesn't do this. Is there another way?

ByteArrayOutputStream baos = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(baos);

for(char ch = 'a';ch <= 'z';ch ++) {
    dos.write(ch);
    dos.flush();
    System.out.println("compressed size = "+baos.toByteArray().length);
}
dos.close();
System.out.println("After close, compressed size = "+baos.toByteArray().length);

What I expect to see is the size increasing on each flush as it flushes any pending/buffered data. However, it doesn't. It just stays in a buffer until I close the stream.

compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
compressed size = 2
After close, compressed size = 34

If DeflaterOutputStream doesn't support this, is there a compressed stream which does?

I have looked at Apache Commons Compress and the only stream which flushes the data is XZCompressorInputStream but in doing so, the data is about 50% larger than not compressing.

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
XZCompressorOutputStream dos = new XZCompressorOutputStream(baos);

for (char ch = 'a'; ch <= 'z'; ch++) {
    dos.write(("Hello world").getBytes());
    baos2.write(("Hello world").getBytes());
    dos.flush();
    System.out.println("compressed size = " + baos.toByteArray().length);
}
dos.close();
System.out.println("After close, compressed size = " + baos.toByteArray().length);
System.out.println("uncompressed size = " + baos2.toByteArray().length);

finally prints

compressed size = 388
After close, compressed size = 424
uncompressed size = 286
Was it helpful?

Solution

I should have read the Javadoc. There is an option to the constructor syncFlush and if true gives the behaviour I want.

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(baos, true);

for (char ch = 'a'; ch <= 'z'; ch++) {
    dos.write(("Hello world").getBytes());
    baos2.write(("Hello world").getBytes());
    dos.flush();
    System.out.println("compressed size = " + baos.toByteArray().length);
}
dos.close();
System.out.println("After close, compressed size = " + baos.toByteArray().length);
System.out.println("uncompressed size = " + baos2.toByteArray().length);

prints finally

compressed size = 212
compressed size = 220
After close, compressed size = 226
uncompressed size = 286

Note: this was only added in Java 7, and I was looking at Java 6.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top