gpt4 book ai didi

java - "Too many open files in system"列出递归目录结构时失败

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:22:25 25 4
gpt4 key购买 nike

我已经(用 Java)实现了一个相当简单的迭代器来返回递归目录结构中的文件名,在大约 2300 个文件之后它失败了“系统中打开的文件太多”(失败实际上是在尝试加载一个类,但我认为目录列表是罪魁祸首)。

迭代器维护的数据结构是一个Stack,保存着每一级打开的目录的内容。

实际逻辑相当基本:

private static class DirectoryIterator implements Iterator<String> {

private Stack<File[]> directories;
private FilenameFilter filter;
private Stack<Integer> positions = new Stack<Integer>();
private boolean recurse;
private String next = null;

public DirectoryIterator(Stack<File[]> directories, boolean recurse, FilenameFilter filter) {
this.directories = directories;
this.recurse = recurse;
this.filter = filter;
positions.push(0);
advance();
}

public boolean hasNext() {
return next != null;
}

public String next() {
String s = next;
advance();
return s;
}

public void remove() {
throw new UnsupportedOperationException();
}

private void advance() {
if (directories.isEmpty()) {
next = null;
} else {
File[] files = directories.peek();
while (positions.peek() >= files.length) {
directories.pop();
positions.pop();
if (directories.isEmpty()) {
next = null;
return;
}
files = directories.peek();
}
File nextFile = files[positions.peek()];
if (nextFile.isDirectory()) {
int p = positions.pop() + 1;
positions.push(p);
if (recurse) {
directories.push(nextFile.listFiles(filter));
positions.push(0);
advance();
} else {
advance();
}
} else {
next = nextFile.toURI().toString();
count++;
if (count % 100 == 0) {
System.err.println(count + " " + next);
}
int p = positions.pop() + 1;
positions.push(p);
}
}
}
}

我想了解这需要多少“打开文件”。该算法在什么情况下“打开”文件,什么时候再次关闭?

我看过一些使用 Java 7 或 Java 8 的整洁代码,但我仅限于使用 Java 6。

最佳答案

当您调用 nextFile.listFiles() 时,将打开底层文件描述符以读取目录。没有办法显式关闭这个描述符,所以你依赖于垃圾收集。当您的代码下降到一棵深树时,它实际上是在收集一堆不能被垃圾收集的 nextFile 实例。

第 1 步:在调用 advance() 之前设置 nextFile = null。这将释放用于垃圾回收的对象。

第 2 步:您可能需要在 null nextFile 后调用 System.gc() 以促进快速垃圾收集。不幸的是,没有办法强制 GC。

第 3 步:您可能需要增加操作系统的打开文件限制。在 Linux 上,这可以通过 ulimit(1) 完成。

如果您可以迁移到 Java 7 或更高版本,那么 DirectoryStream 将解决您的问题。不使用 nextFile.listFiles(),而是使用 Files.newDirectoryStream(nextFile.toPath()) 来获取 DirectoryStream。然后您可以遍历流,然后关闭()它以释放操作系统资源。每个返回的路径都可以使用 toFile() 转换回文件。但是,您可能希望重构为仅使用 Path 而不是 File。

关于java - "Too many open files in system"列出递归目录结构时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33620971/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com