1

I have following two code block, which I use to compress a String.

code 1

public static String compressResponse(String response) throws IOException {

    Deflater deflater = new Deflater(Deflater.DEFLATED, true);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream, deflater);
    try {
        deflaterOutputStream.write(response.getBytes(StandardCharsets.UTF_8));
        return Base64.encodeBytes(byteArrayOutputStream.toByteArray(), Base64.DONT_BREAK_LINES);
    } finally {
        deflaterOutputStream.close();
    }
}

code 2

 public static String compressResponse(String response) throws IOException {

    Deflater deflater = new Deflater(Deflater.DEFLATED, true);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream, deflater);
    try {
        deflaterOutputStream.write(response.getBytes(StandardCharsets.UTF_8));
    } finally {
        deflaterOutputStream.close();
    }
    return Base64.encodeBytes(byteArrayOutputStream.toByteArray(), Base64.DONT_BREAK_LINES);
}

Only the second method works fine where first method always return an empty String. I understand the this different behavior occurs due to different placement of return block with respect to finally block. What is the exact behavior for this?

Chamila Wijayarathna
  • 1,815
  • 5
  • 30
  • 54
  • 4
    The [`close` javadoc](https://docs.oracle.com/javase/8/docs/api/java/util/zip/DeflaterOutputStream.html#close--) says *writes remaining compressed data to the output stream and closes the underlying stream*. Presumably, if you don't `close` there is *remaining* data (i.e. all of it) that hasn't been written to the stream (see also [`flush`](https://docs.oracle.com/javase/8/docs/api/java/util/zip/DeflaterOutputStream.html#flush--)). Also, I would prefer a [`try-with-resources`](http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html). – Elliott Frisch Apr 23 '16 at 14:43
  • @ElliottFrisch " *there is remaining data (i.e. all of it)* " is it right? I knew if we dont call ``close()`` still there is a huge chance that some stream will be transmitted; close() ensure to get 100% data. Am I wrong? – rev_dihazum Apr 23 '16 at 14:49
  • @rev_dihazum It's buffered; there might be any (or no) content remaining in the buffer if you don't `flush` it. Which can lead to very difficult bugs. – Elliott Frisch Apr 23 '16 at 14:54
  • yes.... but my question was: no stream will be transmitted before calling ``close()``? I knew stream will be transmitted ; close just flush the buffer – rev_dihazum Apr 23 '16 at 14:56

3 Answers3

2

On the second example byteArrayOutputStream gets populated because deflaterOutputStream is closed and flushed.

0

The reason is because in the first method the return statement is executed before you do the deflaterOutputStream.close(); While the second do the close operation first

deflaterOutputStream writes the data to byteArrayOutputStream when it close the connection. Until deflaterOutputStream is closed, byteArrayOutputStream doesn't contain data.

Chamila Wijayarathna
  • 1,815
  • 5
  • 30
  • 54
Dazak
  • 1,011
  • 2
  • 9
  • 17
  • How does closing deflaterOutputStream after returning affect the output of the method? If it hasn't closed, still Base64.encodeBytes(byteArrayOutputStream.toByteArray(), Base64.DONT_BREAK_LINES) should return a correct value, isn't it? – Chamila Wijayarathna Apr 23 '16 at 14:38
  • No, it is supposed that if you don't close it, it won't release the memory and won't write, it means that it doesn't return the correct value... – Dazak Apr 23 '16 at 14:39
  • So when we close deflatedOutputStream, it write/flush the values to byteArrayOutputStream? – Chamila Wijayarathna Apr 23 '16 at 14:42
  • 1
    Exactly, just as @dur said – Dazak Apr 23 '16 at 14:43
-1

Even though you placed return statement in try block, your finally block will executes, functionality of finally block is,

If exception raised or not raised, even though if exception raised and handled or not handled then finally block will execute, finally block won't execute if you place system.exit() in try or catch block

In your code

try{
return------> this wont return instead finally block will execute
}
finally{
//
}

Your closing DeflaterOutputStream and it flushed so it is returning empty

subbu royal
  • 584
  • 4
  • 12
  • 29