Java8 file stream, how to control file closure?

Suppose I have Java8 Stream<FileReader>and what I use this thread for mapand the like, how can I control the closure FileReaderused in the thread?

Note that I may not have access to individual FileReaders, for example:

filenames.map(File::new)
    .filter(File::exists)
    .map(f->{
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(f));
        } catch(Exception e) {}
            return Optional.ofNullable(br);
        })
    .filter(Optional::isPresent)
    .map(Optional::get)
    .flatMap(...something that reads the file contents...) // From here, the Stream doesn't content something that gives access to the FileReaders

After doing some other comparisons, etc., I finally lose FileReaderin the future.

At first I thought that the garbage collector could do this when necessary, but I experienced running out of the OS descriptor when filenameslong Stream.

+5
source share
5 answers

FileReader: FileReader FileInputStream finalize() , , .

Java- Java 7, API java.nio.files, BufferedReader

 Path path = Paths.get(filename);
 BufferedReader br = Files.newBufferedReader(path);

,

 filenames.map(Paths::get)
          .filter(Files::exists)
          .map(p -> {
        try {
            return Optional.of(Files.newBufferedReader(p));
        } catch (IOException e) {
            return Optional.empty();
        }
    }) 

:

1

Reader - Tuple. ( ) -, :

class ReaderTuple<T> {
   final Reader first;
   final T second;
   ReaderTuple(Reader r, T s){
     first = r;
     second = s;
   }
}

FileReader , :

 filenames.map(Paths::get)
  .filter(Files::exists)
  .map(p -> {
        try {
            return Optional.of(Files.newBufferedReader(p));
        } catch (IOException e) {
            return Optional.empty();
        }
    }) 
  .filter(Optional::isPresent)
  .map(Optional::get)
  .flatMap(r -> new ReaderTuple(r, yourOtherItem))
  ....
  .peek(rt -> {
    try { 
      rt.first.close()  //close the reader or use a try-with-resources
    } catch(Exception e){}
   })
  ... 

, , FlatMap peek, .

2

, try-with-resources. , .

1:

 filenames.map(Paths::get)
  .filter(Files::exists)
  .map(p -> {
        try (Reader r = new BufferedReader(new FileReader(p))){

            Stream.of(r)
            .... //put here your stream code that uses the stream

        } catch (IOException e) {
            return Optional.empty();
        }
    }) //reader is implicitly closed here
 .... //terminal operation here

2:

filenames.map(Paths::get)
  .filter(Files::exists)
  .map(p -> {
        try {
            return Optional.of(Files.newBufferedReader(p));
        } catch (IOException e) {
            return Optional.empty();
        }
    }) 
 .filter(Optional::isPresent)
 .map(Optional::get)
 .flatMap(reader -> {
   try(Reader r = reader) {

      //read from your reader here and return the items to flatten

   } //reader is implicitly closed here
  }) 

1 , . 2 , try-with-resources, .

1 , , .

+4

, Consumer<FileReader> .

, , , . , , .

, , Consumer<BufferedReader>

, , , , , .

public void readAllFiles( Consumer<BufferedReader> consumer){
    Objects.requireNonNull(consumer);

    filenames.map(File::new)
             .filter(File::exists)
             .forEach(f->{

                 try(BufferedReader br = new BufferedReader(new FileReader(f))){
                     consumer.accept(br);
                 } catch(Exception e) {
                     //handle exception
                 }
             });
}

, , .

,

 readAllFiles( br -> System.out.println( br.lines().count()));
+3

, , - :

List<String> fileNames = Arrays.asList(
            "C:\\Users\\wowse\\hallo.txt",
            "C:\\Users\\wowse\\bye.txt");

fileNames.stream()
            .map(Paths::get)
            .filter(Files::exists)
            .flatMap(path -> {
                try {
                    return Files.lines(path);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            })
            .forEach(System.out::println);

, , .

fileNames.stream()
            .map(Paths::get)
            .filter(Files::exists)
            .map(path -> {
                try {
                    return Files.readAllBytes(path);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            })
            .filter(Objects::nonNull)
            .map(String::new)
            .forEach(System.out::println);

, , -, Map.Entry Pair javafx, - .

+1

, , , , , SO.

java.nio.file , :

filenames.map(Paths::get)
    // Nicer alternative to File::exists
    .filter(Files::exists)
    // This will automatically close the stream after each file is done reading
    .flatMap(path -> {
        try {
            return Files.lines(path);
        } catch (IOException e) {
            // Seamlessly handles error opening file, no need for filtering
            return Stream.empty();
        }
    })
    .map(/* Do something with each line... */)
0

Just for the sake of argument (although I agree with Louis above): You can pass the original Reader/ InputStream(or any object, but the case you provided is really a programming mistake, because you can pass FileReaderinstead of encapsulating it with BufferedReader), using common- lang3 Pairclass. Jool is also a valid library that provides classes Tuple*.

Example:

filenames.map(File::new)
    .filter(File::exists)
    .map(f->{
        BufferedReader br = null;
        FileReader fr = null;
        try {
            fr = new FileReader(f)
            br = new BufferedReader(fr);
            return Optional.of(Pair.of(br,fr)) ;
        } catch(Exception e) {}
            return Optional.ofNullable(br);
        })
    .filter(Optional::isPresent)
    .map(Optional::get)
    .flatMap( pair -> { 
        try {
            // do something with br               
        } finally {
             try {
                 pair.getRight().close();
             } catch (IOException x ){
                 throw new RuntimeException(x) ;
             }
        }
    })       
-2
source

Source: https://habr.com/ru/post/1675203/


All Articles