Java8流文件,如何控制文件的关闭?
假设我有一个Java8 Stream<FileReader>
,并且使用了该流map
,那么如何控制FileReader
流中使用的s 的关闭?
请注意,我可能无权访问个人FileReader
,例如:
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
在进行了其他一些映射等之后,我终于FileReader
在续集中失去了。
我首先认为垃圾收集器可以在需要时执行此操作,但是当filenames
它很长时,我已经经历了OS描述符耗尽Stream
。
回答:
关于使用FileReader的一般注意事项:FileReader在内部使用FileInputStream,它会覆盖finalize()
并且因此不建议使用它对垃圾回收的影响,尤其是在处理大量文件时。
除非您使用的是Java 7之前的Java版本,否则应改用java.nio.files API,使用以下命令创建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();
}
})
现在到您的问题:
回答:
保存原件的一种方法Reader
是使用元组。通常,元组(或其任何n元变体)是处理函数应用程序的多个结果的好方法,因为它是在流管道中完成的:
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之间执行流期间发生未经检查的异常,读者就可能不会关闭。
回答:
使用元组的另一种方法是将需要阅读器的代码放在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,并将访问读者的代码放在单独的函数中,以使代码更易读。
以上是 Java8流文件,如何控制文件的关闭? 的全部内容, 来源链接: utcz.com/qa/424452.html