0

I'm hoping someone can shed light on a problem I'm having with the code below.

private static String encode(String data) throws IOException {
        try (
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            InputStream is = new ByteArrayInputStream(data.getBytes());
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            OutputStreamWriter writer = new OutputStreamWriter(new GZIPOutputStream(out));
            ) {
            char[] charBuffer = new char[data.length()];
            while (br.read(charBuffer) != -1) {
                writer.write(charBuffer);
            }
//          writer.close();
            return new String(Base64.encodeBase64(out.toByteArray()));
        }
    }

My test value is

This is some text that I can test some base64 encoding with.
I am getting a strange problem with the encoded value

when writer.close is commented out, my output is

H4sIAAAAAAAAAA==

When it's not commented, my output is

H4sIAAAAAAAAACWMzQ2DMBSD70jdwRP0VLED9y7wACuJRJKKZ37GJxTJF/uz/Y3J0eQ1E+IpKJowYLLSvOshozn7D1imOqcScCTF96sbYBmB0p0ZXKuVQPzWOi7M/1b747PjjN2WjRd08DfZcwAAAA==

This second output is the correct value and can be decoded back into the original value. It is my understanding that the process is as follows:

  1. Try code is executed
  2. Return value is evaluated and stored
  3. Resources are all closed
  4. The return value is returned.

Why then does the writer need to be closed for the output to be correct?

Matt R
  • 1,276
  • 16
  • 29
  • Try adding writer.flush() instead of close. It could be that the stream hasn't been fully written before you read from it. – Andrew Vitkus May 08 '14 at 06:46
  • @AndrewVitkus Sorry I should have mentioned that I had also tried flush. Flush instead of close still results with the incorrect encoding unfortunately. – Matt R May 08 '14 at 06:48
  • 1
    I would retry with flush(). Also, to be correct, your code should only write the number of chars that have actually been read by `br.read()`, and not the wole char array. – JB Nizet May 08 '14 at 06:51
  • Since closing writer should close out too you could just have out declared outside the try and assigned in it. Then you could just move the return to outside the try as well. Of course, that requires null checks for out and other such unpleasantries so just including the close might be the most elegant solution. – Andrew Vitkus May 08 '14 at 06:54
  • Sorry, I was wrong in my previous comment. The GZIP stream must be closed in order for the compression to be finished and for the result to be written. So, flush the writer, and close at least the gzip stream. Closing the writer won't hurt anyway. – JB Nizet May 08 '14 at 06:58
  • possible duplicate of [How does BufferedOutputStream actually work at a low level?](http://stackoverflow.com/questions/9282909/how-does-bufferedoutputstream-actually-work-at-a-low-level) – Damian Leszczyński - Vash May 08 '14 at 07:10

2 Answers2

0

Its because when we close the writer it flushes the stream. When you dont close the writer it does not get flushed (Buffer is flushed automatically only when it gets full or it is closed). So u can do it explicitly by writing

writer.flush()
Mustafa sabir
  • 4,130
  • 1
  • 19
  • 28
0

A GZIP output stream has to be told when to finish the compression and write the result to the underlying stream. close() implicitely flushes the writer and calls finish() on the GZIP stream.

So, call at least flush() on the writer and finish() or close() of the GZIP stream, or close the writer, which will do all that and won't hurt anyway.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255