38

Is this code

    BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
    try {
        bw.write("test");
    } finally {
        IOUtils.closeQuietly(bw);
    }

safe or not? As far as I understand when we close a BufferedWriter it will flush its buffer to the underlying stream and may fail due to an error. But IOUtils.closeQuietly API says that any exceptions will be ignored.

Is it possible a data loss will go unnoticed due to IOUtils.closeQuietly?

pidabrow
  • 886
  • 1
  • 19
  • 40
Evgeniy Dorofeev
  • 124,221
  • 27
  • 187
  • 258
  • 8
    Not an answer, but [try-with-resources](http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) statement will eliminate most needs for using `IOUtils.closeQuietly`. – lyomi Oct 02 '13 at 07:08
  • 1
    Good answer, but this feature is new in Java 7. If you're stuck using Java 6 for some reason (e.g. older Android versions) then `closeQuietly()` is still the way to go. – Edward Falk Apr 05 '16 at 22:44
  • IOUtils.closeQuietly HAS BEEN DEPRECATED NOW use try with resource instead. – best wishes Apr 30 '19 at 05:11
  • closeQuietly(..) is still necessary if the close() method of the resource throws an checked exception. In this case try-with-resources can't be used as an exception on close() will bubble up. – Sven Döring Mar 08 '21 at 10:40

4 Answers4

41

The code should look like this regarding to the javadoc of closeQuietly():

BufferedWriter bw = null;

try {
    bw = new BufferedWriter(new FileWriter("test.txt"));
    bw.write("test");
    bw.flush(); // you can omit this if you don't care about errors while flushing
    bw.close(); // you can omit this if you don't care about errors while closing
} catch (IOException e) {
    // error handling (e.g. on flushing)
} finally {
    IOUtils.closeQuietly(bw);
}

closeQuietly() is not intended for general use instead of calling close() directly on a Closable. Its intended use-case is for ensuring the close inside a finally-block - all error handling you need have to be done BEFORE that.

That means, if you want to react on Exceptions during the call of close() or flush() then you've to handle it the normal way. Adding closeQuietly() in your finally-block just ensures the close, e.g. when the flush failed and close was not called in try-block.

Edward Falk
  • 9,578
  • 8
  • 66
  • 105
Fabian Barney
  • 13,133
  • 4
  • 37
  • 60
  • I think bw.flush() is unnecessary, bw.close() calls flush() anyway – Evgeniy Dorofeev Jan 21 '13 at 11:21
  • 2
    @EvgeniyDorofeev Yep, as long as you leave the `close()` in there. But when you only care about exceptions during flush but not close then you need to flush here explicitly. Just wrote both method calls to make the example a bit more universal. – Fabian Barney Jan 21 '13 at 11:27
  • Just to be clear: you *can* omit the call to `bw.close()` and bw will still be closed properly in the finally{} clause. Doing it this way also allows you to learn of any errors during `bw.close()` – Edward Falk Apr 05 '16 at 22:58
  • 1
    `close()` doesn't always call `flush()` and sometimes `close()` calls flush but with the `IOException` masked in it. See `FilterOutputStream` for example. – Gray Apr 17 '19 at 22:01
8

It is safe so long as your application doesn't care whether the write succeeded without error. If your application needs to handle write errors it is not safe as buffered data flushed on close may be lost and the error swallowed.

McDowell
  • 102,869
  • 29
  • 193
  • 261
6

Yes, it's safe to use it but only for Java6 and lower. From Java7, you should user try-with-resource.

It will eliminate much of the boilerplate code you have and the need to use IOUtils.closeQuietly.

Now, you example:

    BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
    try {
        bw.write("test");
    } finally {
        IOUtils.closeQuietly(bw);
    }

Can be written as:

   try (BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"))) {
       bw.write("test");
   }

It's important to note that in order to use the try-with-resource approach, your resource need to implement a new interface called java.lang.AutoCloseable that was introduced in Java 7.

Also, you can include a number of resources in a try-with-resource block, just separate them with ;

   try (
       BufferedWriter bw1 = new BufferedWriter(new FileWriter("test1.txt"));
       BufferedWriter bw2 = new BufferedWriter(new FileWriter("test2.txt"))
   ) {
       // Do something useful with those 2 buffers!
   }   // bw1 and bw2 will be closed in any case
Johnny
  • 10,849
  • 11
  • 61
  • 105
5

It is possible in theory but I can't say I have ever seen close() fail. Usually fail fast means that a previous IO operations such as opening the file will fail first. You can write a close which doesn't ignore IOExceptions but this could clobber the true cause of an exception if it is something in the try/catch block which failed.

What you want is something like the following (which is overkill in most cases)

try {
    // write to bw.
    bw.close(); // throw IOException if an error occurs.

} finally {
    // don't clobber a previous IOException
    IOUtils.closeQuietly(bw);
}
Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
  • 2
    You are using it incorrectly - `IOUtils.closeQuietly()` is not intended for general use instead of calling close() directly on a Closable. Its intended use case is to ensure that close() is called inside a finally block to avoid resource leak - all error handling (logging, exception wrapping and rethrowing) should be done BEFORE that - see Fabian's answer – Jarek Przygódzki Oct 16 '13 at 17:26
  • @JarekPrzygódzki When was the last time you saw an IOException on close specifically? – Peter Lawrey Oct 16 '13 at 22:48
  • It's rare but it does happen - you never know what's behind the Closeable or {Input, Output}Stream. And silencing exceptions is almost never good. – Jarek Przygódzki Nov 07 '13 at 23:07
  • 2
    I've examined the [source code](https://commons.apache.org/proper/commons-io/apidocs/src-html/org/apache/commons/io/IOUtils.html) and read the documentation. `closeQuietly()` is little more than a call to `close()` surrounded by a try/catch that ignores exceptions. The documentation agrees. You **can** use `closeQuietly()` in place of close(), and the `finally{ }` block is the ideal place to do this. – Edward Falk Apr 05 '16 at 22:53