23

This almost seems silly but what is the most reliable pattern to follow when closing an OutputStream? Right now I have something like the following which just seem to be try-catch-finally-overkill:

private void writeContentsToFile(OutputStream ostream, Properties contents) {
    try {
        contents.store(ostream, "comments");
    }
    catch (IOException e) {
        throw new ResourceException("Failed to write contents", e);
    }
    finally {
        try {
            ostream.close();
        }
        catch (IOException e) { /* what can be done here anyway? */ }
    }
}

Why close throws a checked exception is still a mystery to me. I can create wrapper method that does the close/catch block but if there is something already out there like FileUtil.closeFileAndThrowUncheckedException() I would like to use it. This gets a bit more useful when you have lots of smaller projects with lots of devs; one way to do it right.

Andrew White
  • 52,720
  • 19
  • 113
  • 137
  • 1
    close() might write data. if e.g. an underlying stream buffers data, close() will flush the data - and that might fail for the same reason a write call could fail.(in the case of e.g. sockets, it's possible close() could signal a failure from one of the prior write calls as well) – nos Jun 07 '11 at 17:21
  • Consider using a Writer instead of working with the stream directly. Writers offer a lot of conveniences if you use one tailored to the task. For example, when storing your properties using a `BufferedWriter` would be a good choice. If you look at the source code you'll see it flushes and closes the stream, though you'll still have to deal with the "extra" IOException. – Paul Jun 07 '11 at 17:26
  • @Paul: I usually do but I used the OutputStream for this case just as a quick example. – Andrew White Jun 07 '11 at 17:30
  • In your last catch, you can `throw new RuntimeException(e)`. It is unchecked and you won't hide the exception. – Carcamano Jun 07 '11 at 17:31
  • @Raedwald, I have flagged this question for re-opening. Although it is indeed a duplicate, it is now the top result on Google for the obvious search (I won't add the search terms in here else it will reinforce the effect). The answer is very obviously out of date as well. I think this question ought to be re-opened and the correct answer posted. – Rudi Kershaw Mar 03 '20 at 11:19
  • @RudiKershaw Except *all* the answers here are wrong. – Raedwald Mar 03 '20 at 17:33
  • @Raedwald, I agree. But traffic is being directed here, and people can't post a correct answer to mitigate unless it is open. – Rudi Kershaw Mar 04 '20 at 10:12
  • @RudiKershaw The *whole point* of marking questions as duplicates is to redirect traffic to the correct or canonical answer. – Raedwald Mar 04 '20 at 12:07

3 Answers3

18

If you are using Apache Commons, then IOUtils.closeQuietly() does the job nicely. See http://commons.apache.org/proper/commons-io/javadocs/api-1.4/org/apache/commons/io/IOUtils.html#closeQuietly(java.io.OutputStream)

dwikle
  • 6,820
  • 1
  • 28
  • 38
Sripathi Krishnan
  • 30,948
  • 4
  • 76
  • 83
  • How did I miss that? I thought I looked through IOUtils. I'll give the question some time for more feedback but this is looking spot on. – Andrew White Jun 07 '11 at 17:27
  • When I used to implement this I would typically wrap the IOException with a RuntimeException and just throw it again, but closeQuietly is actually swallowing the exception. Which is better? – Ring May 31 '16 at 14:57
2

I don't think the exception should be swallowed. The caller is misled to believe that the content is written successfully. The exception should propagate upwards.

If you don't like checked exceptions (especially for such low level errors), wrap it as unchecked. Or you can follow Java's convention, for better or for worse, and declare IOException on your method.

irreputable
  • 44,725
  • 9
  • 65
  • 93
-1

I think your way is the 'best' way. If close throws an exception, you indeed just cannot do anything about it. This probably throws an caught exception because it might be bad, depending on how it's used. If you really need to close a file you would like to enforce it. If you just want to use close for errorhandling, you should just ignore the exception.

Vincent Koeman
  • 751
  • 3
  • 9