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

Peter Levart peter.levart at gmail.com
Mon Nov 18 15:39:36 UTC 2013


On 11/18/2013 03:28 PM, Brian Goetz wrote:
> Which means that, if your stream holds non-memory resources, the 
> flatMapper should create a stream that closes the underlying stream, 
> like:
>
>   blah.flatMap(path -> {
>      BufferedReader br = new BufferedReader(path);
>      return br.lines.onClose(br::close);
>   }
>   ... 

...the only problem with above code is that it doesn't compile, because 
of IOException declared on BufferedReader (FileReader actually!) 
constructor and BufferedReader.close() method. The solutions to this 
have already been discussed on the list some time ago, and one of the 
propositions was to create interfaces like:


public interface IOFunction<T, R> extends Function<T, R> {
     default R apply(T t) {
         try {
             return applyIO(t);
         } catch (IOException e) {
             throw new UncheckedIOException(e);
         }
     }

     R applyIO(T t) throws IOException;
}


public interface IORunnable  extends Runnable {
     default void run() {
         try {
             runIO();
         } catch (IOException e) {
             throw new UncheckedIOException(e);
         }
     }

     void ruinIO() throws IOException;
}


...etc, and use them in code like this:


List<String> paths = ...
paths
     .stream()
     .flatMap((IOFunction<String, Stream<String>>) path -> {
         BufferedReader br = new BufferedReader(new FileReader(path));
         return br.lines().onClose((IORunnable) br::close);
     })
     .forEach(System.out::println);



Regards, Peter





More information about the core-libs-dev mailing list