2

I want to write base64-encoded data to a file, decoding on the fly. I have

BufferedWriter bw = new BufferedWriter(
  new OutputStreamWriter(
    new Base64OutputStream(
      new FileOutputStream(myFile, false)));

I think this works, and in my finally block I call bw.close() -- that is, close the outermost wrapper. Is that enough, or are some of the anonymous intermediary objects going to leak?

I tried looking through the code but I got stuck at Sun's proprietary implementation of OutputStreamWriter's encoding-handlers. It also doesn't appear to be spelled out explicitly in the documentation.

Community
  • 1
  • 1
Coderer
  • 25,844
  • 28
  • 99
  • 154
  • 3
    Dup of: http://stackoverflow.com/questions/6586866/closing-nested-streams and of: http://stackoverflow.com/questions/8080649/do-i-have-to-close-fileoutputstream-which-is-wrapped-by-printstream – sara Sep 29 '13 at 11:43
  • I don't know why I couldn't find those. Thanks @sara! – Coderer Sep 29 '13 at 13:05

3 Answers3

8

In general closing the outermost wrapper is enough; each wrapper closes the underlaying stream when it's closed.

It is possible to create a wrapper that doesn't do this, but that could be considered a bug since the documentation for FilterOutputStream requires that a call to close "releases any system resources associated with the stream."

Joni
  • 108,737
  • 14
  • 143
  • 193
  • 1
    The only class in JDK which I know to break this rule is `ZipOutputStream` which requires separate entry closing before calling `#close()`. – Esko Sep 29 '13 at 12:29
3

The best approach is to close the outermost stream object. Assuming that it is correctly implemented, this will call close() on the object that wraps, and the closes will propagate up the chain ... doing the right thing.

In the case of an output pipeline, it is actually important that you do it this way. If you only close the innermost outputstream / writer, there is a chance that buffered output (somewhere in the pipeline) won't be written properly.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
2

Since BufferedWriter extends AutoClosable, you can use try-with-resources statement in Java 7 to automatically close the resources when they are out of scope.

try(BufferedWriter bw = new BufferedWriter(
  new OutputStreamWriter(
    new Base64OutputStream(
      new FileOutputStream(myFile, false)));
   ) {

      // bw.write(); 

} catch(XXXException ex) {
    // Catch Block.
}

The try-with-resources statement ensures that each resource is closed at the end of the statement

Also, the code looks cleaner this way.

TheKojuEffect
  • 20,103
  • 19
  • 89
  • 125
  • I have to support Java 6, at least for the foreseeable future. I'd definitely rather do this, though. – Coderer Sep 29 '13 at 13:04