34

Will try-with-resources call flush() implicitly?

If it does, in the following code snippet, bw.flush() can be safely removed?

static void printToFile1(String text, File file) {
    try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
        bw.write(text);
        bw.flush();
    } catch (IOException ex) {
        // handle ex
    }
}

ps. I don't see any description about it in official document:

https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html

Nilesh Thakkar
  • 1,442
  • 4
  • 25
  • 36
petertc
  • 3,607
  • 1
  • 31
  • 36
  • 4
    no. but `close()` usually does flushing anyway. – ZhongYu Sep 01 '15 at 05:59
  • 2
    5 answers so far, *all* quoting the javadoc. Guess that's a sign to *read the doc*. – Andreas Sep 01 '15 at 06:40
  • @ZhongYu Does the word `usually` works as anyone expected? – Jin Kwon Nov 08 '19 at 18:44
  • @Andreas all those answers quote the Javadoc of some Writer class. Thus they all answer only the second, follow-up question of the OP. Only one answer _addresses_ the first, more general question (but does not really answer it, either). – Qw3ry Dec 02 '19 at 13:53
  • 1
    @Qw3ry What do you mean? They all answer it, by quoting the `Writer` javadoc saying that closing auto-flushes for you. The question is *entirely* about `Writer`, because it is the Writer class, not the (Auto)Closeable interface, that *declares* the **`flush()`** method that is the primary topic of the question, so there is no "more general" answer to the question. – Andreas Dec 02 '19 at 22:14
  • @Andreas it's true that (Auto)Closeable doesn't declare `flush()`, but actually it's not `Writer` that declares it either. The [`Writer`-Javadoc](https://docs.oracle.com/javase/7/docs/api/java/io/Writer.html#flush()) of `flush()` explicitely refers to the declaration in `Flushable`. Writer only _overrides_ `flush()`. Because `Flushable` does not extend (Auto)Closeable, its declaration cannot say anything on implementions of `close()`. – Qw3ry Dec 03 '19 at 11:52

6 Answers6

29

Closeable and AutoCloseable are general-purpose interfaces that do not know anything about flushing. So you can't find any information about it in their documentation - except some words about releasing resources.

A Writer on the other hand is a more specific-purpose abstract class that now knows something about flushing. Some excerpt of the documentation for the method Writer.close():

Closes the stream, flushing it first.

So - yes - when using a writer, a close will always also flush. This basically means that you have to consult the documentation of the concrete classes that you are using when trying to find out what closing really does.

Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66
11

The resources are automatically closed when using try-with-resource block. As part of this process it will also invoke flush automatically.

As mentioned in doc for close method of BufferedWriter:

Closes the stream, flushing it first. Once the stream has been closed, further write() or flush() invocations will cause an IOException to be thrown.

akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
5

I really don't understand why other answers focus on the BufferedWriter not try-with-resources.

I, either, couldn't find any specification or mentions that the try-with-resources statements calls flush() on any objects of Flushable.

https://docs.oracle.com/javase/specs/jls/se13/html/jls-14.html#jls-14.20.3

Don't rely on any undocumented/unspecified behavior of vendor specific implementations.

try (OutputStream o = open()) {
    //writeSome
    o.flush(); // won't hurt!
}
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
4

Quoting javadoc of BufferedWriter.close():

Closes the stream, flushing it first.

Andreas
  • 154,647
  • 11
  • 152
  • 247
4

The minimum amount of code to be written in this case:

try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
    bw.write("Test");
} catch (IOException e) {
    // handle exception
}

Hence you don't need to call explicitly the flush method, as it will be called by the close method, as explained in the javadoc:

Closes the stream, flushing it first. Once the stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously closed stream has no effect.

This behavior is inherited from the Writer class, hence besides BufferedWriter the same behavior is provided also by: CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter.

This behavior is not provided in the documentation of the tryWithResources or AutoCloseable as the behavior is specific to the given implementation of Writer. As Writerextends Closeable, it will call the close method when exiting the try {} block and the close method will first call flush as already mentioned.

Olimpiu POP
  • 5,001
  • 4
  • 34
  • 49
2

From the Javdocs:

The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.

The BufferedWriter.close() explicitly stated that:

Closes the stream, flushing it first. Once the stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously closed stream has no effect.

Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331