we are working on a program where we need to flush (force compress and send data) a GZIPOutputStream. The problem is, that the flush method of the GZIPOutputStream doesn't work as expected (force compress and send data), instead the Stream waits for more data for efficient data compression.
When you call finish the data is compressed and sent over the output stream but the GZIPOutputStream (not the underlying stream) will be closed so we cant write more data till we create a new GZIPOutputStream, which costs time and performance.
Hope anyone can help with this.
Best regards.
解决方案
I didn't find the other answer to work. It still refused to flush because the native code that GZIPOutputStream is using holds onto the data.
Thankfully, I discovered that someone has implemented a FlushableGZIPOutputStream as part of the Apache Tomcat project. Here is the magic part:
@Override
public synchronized void flush() throws IOException {
if (hasLastByte) {
// - do not allow the gzip header to be flushed on its own
// - do not do anything if there is no data to send
// trick the deflater to flush
/**
* Now this is tricky: We force the Deflater to flush its data by
* switching compression level. As yet, a perplexingly simple workaround
* for
* http://developer.java.sun.com/developer/bugParade/bugs/4255743.html
*/
if (!def.finished()) {
def.setLevel(Deflater.NO_COMPRESSION);
flushLastByte();
flagReenableCompression = true;
}
}
out.flush();
}
You can find the entire class in this jar (if you use Maven):
org.apache.tomcat
tomcat-coyote
7.0.8
Or just go and grab the source code FlushableGZIPOutputStream.java
It's released under the Apache-2.0 license.