c++返回指针时候注意提防
Java8中有一个非常不错的新功能,它使您可以在一个内衬中从文件中获取字符串流。
List lines = Files.lines(path).collect(Collectors.toList());
您可以像处理任何其他Stream一样操作Stream,例如,您可能需要filter()或map()或limit()或skip()等。我开始在代码中使用它,直到遇到异常,
Caused by: java.nio.file.FileSystemException: /tmp/date.txt: Too many open files in system
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:91)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
at java.nio.file.Files.newByteChannel(Files.java:361)
at java.nio.file.Files.newByteChannel(Files.java:407)
at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384)
at java.nio.file.Files.newInputStream(Files.java:152)
at java.nio.file.Files.newBufferedReader(Files.java:2784)
at java.nio.file.Files.lines(Files.java:3744)
at java.nio.file.Files.lines(Files.java:3785)
由于某些原因,我打开的文件太多了! 奇怪,Files.lines()是否关闭文件?
请参阅下面的代码( run3()
),其中创建的内容再现了该问题:
package utility;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.stream.Stream;
public class Test2 {
public static void main(String[] args) throws IOException{
int times = 100_000;
Path path = Paths.get("/tmp", "date.txt");
Test2 t2 = new Test2();
t2.setDate(path);
for (int i = 0; i < times; i++) {
t2.run1(path);
}
for (int i = 0; i < times; i++) {
t2.run2(path);
}
for (int i = 0; i < times; i++) {
t2.run3(path); //throws exception too many files open
}
System.out.println("finished");
}
public String run1(Path path){
try(BufferedReader br = new BufferedReader(new FileReader(path.toFile()))){
return br.readLine();
} catch (IOException e) {
throw new AssertionError(e);
}
}
public String run2(Path path){
try(Stream<String> stream = Files.lines(path)) {
return stream.findFirst().get();
} catch (IOException e) {
throw new AssertionError(e);
}
}
public String run3(Path path) throws IOException{
return Files.lines(path).findFirst().get();
}
public void setDate(Path path) {
try (FileWriter writer = new FileWriter(path.toFile())){
writer.write(new Date().toString());
writer.flush();
} catch (IOException e) {
throw new AssertionError(e);
}
}
}
我的代码看起来像run3()
,它产生了异常。 我通过运行unix命令lsof
(列出打开的文件)并注意到许多date.txt实例打开来证明这一点。 要检查这个问题确实与Files.lines()
我确信,代码跑了run1()
使用BufferedReader
,它做到了。 通过阅读Files
的源代码,我意识到Stream需要以可自动关闭的方式创建 。 当我在run2()
该代码时,代码再次正常运行。
我认为这并不是特别直观。 当您必须使用自动关闭装置时,它确实损坏了一个衬管。 我猜想代码确实需要有关何时关闭文件的信号,但是如果对我们隐藏了,不知何故还是不错的。 至少应该在JavaDoc中突出显示它,而不是:-)
翻译自: https://www.javacodegeeks.com/2015/02/java-8-pitfall-beware-files-lines.html
c++返回指针时候注意提防