Why stream from BufferedReader::lines is not closing the reader?

Gernot Neppert mcnepp02 at googlemail.com
Mon Nov 18 10:03:46 UTC 2013

Hi Tomasz,

I think the answer to your question "Why does the stream from
BufferedReader.lines() not close the Reader?" is:
Because the stream did not open the Reader!

It mainly boils down to following a well-proven convention: Whoever creates
a Resource is responsible for closing it.

Thus, you should wrap your BufferedReader in a try-with-resources-block and
be done with it,
or resort to the static method java.nio.files.Files.lines(Path, Charset).
That one does indeed create the underlying resource, and thus, as you'd
expect, disposes of it in the Stream's close method!

2013/11/18 Tomasz Kowalczewski <tomasz.kowalczewski at gmail.com>

> Hi,
> I am starting to learn how streams interact with I/O and I have question on
> java.io.BufferedReader::lines method. Please excuse me if this is not the
> right list (I did not found core-libs-discuss or similar).
> I am using build 115.
> The stream returned by call to ::lines does not close the reader after
> terminal operation is executed (e.g. collect()). Javadoc for this method
> states that:
>    * <p> After execution of the terminal stream operation there are no
>      * guarantees that the reader will be at a specific position from which
> to
>      * read the next character or line.
> This implies that the reader is not closed. But:
> 1. For clarity it might be good to spell it out that reader is not closed.
> 2. If, according to the javadoc, the reader is left in undefined state
> after stream terminal operation  then why not close it already? I know that
> I can read more lines from it afterwards and it will work, others will
> notice it too. This might lead to unpleasant surprises once some (minor or
> major) java update changes the implementation and all code relying in this
> feature will break in subtle ways (e.g. missing a line or two).
> 3. If I want the stream to be closed I need to do:
> reader.lines().onClose(is::close).doStreamyStuff().collect(...);
> where *is* is an underlying InputStream.
> The problem with this code is that ::close throws IOException which is not
> compatible with Runnable accepted by onClose(); Is there a better way? Some
> wrapper I can use to inject a call to close?
> --
> Regards,
> Tomasz Kowalczewski

More information about the core-libs-dev mailing list