我有下面的代码,它只是读取文件夹中的所有文件。此文件夹中有20,000个文件。该代码在本地文件夹(d:/files
)上运行良好,但在读取大约1,000 - 2,000个文件后在网络路径(//robot/files
)上失败。
更新:文件夹是彼此的副本。
导致此问题的原因以及解决方法是什么?
package cef_debug;
import java.io.*;
public class Main {
public static void main(String[] args) throws Throwable {
String folder = args[0];
File[] files = (new File(folder)).listFiles();
String line;
for (int i = 0; i < files.length; i++) {
BufferedReader br = new BufferedReader(new FileReader(files[i]));
while ((line = br.readLine()) != null) {
}
br.close();
}
}
}
从网络路径(//robot/files
)读取时出现以下错误:
Exception in thread "main" java.io.IOException: Too many open files
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:106)
at java.io.FileReader.<init>(FileReader.java:55)
at cef_debug.Main.main(Main.java:12)
Java Result: 1
第12行是行:
BufferedReader br = new BufferedReader(new FileReader(files[i]));
答案 0 :(得分:3)
某些java版本有一个documented bug,有些文件打开到2035的限制。你可能只是点击它。
来自评论:
为了澄清这个问题,在win32系统上有三种打开方式 文件:
1:使用Win32 API
2:使用MFC类框架库。
3:使用C-Library API(open()和fopen())
除第三种选择外,即选项1和2实际上没有 开放文件数量的限制。第三种方法受到限制 (因为我不知道的原因)只打开约。 2035个文件。那 这就是为什么MS JVM能够打开无限(实际)文件,但SUN 2035文件后JVM失败(我的猜测是使用第三种方法) 打开文件)。
现在,这是一个很久以前修复过的旧问题,但是他们可能会在网络访问中使用相同的功能,但错误仍然存在。
即使没有关闭句柄或流,Windows也应该能够打开&gt; 10000文件句柄并保持打开状态,如错误评论中的测试代码所示:
import java.util.*;
import java.io.*;
// if run with "java maxfiles 10000", will create 10k files in the current folder
public class maxfiles
{
static int count = 0;
static List files = new ArrayList();
public static void main(String args[]) throws Exception
{
for (int n = 0; n < Integer.parseInt(args[0]); n++) {
File f = new File("file" + count++);
//save ref, so not gc'ed
files.add(new PrintStream(new FileOutputStream(f)));
}
Iterator it = files.iterator();
while (it.hasNext()) {
PrintStream out = ( PrintStream) it.next();
out.println("foo");
out.flush();
}
System.out.println("current files open: " + files.size());
} //~main
}
您可以测试在网络共享上运行它,并在失败时报告错误。您也可以尝试使用其他JDK。至少使用OpenJDK源代码,我看不到除WinAPI调用之外的任何其他调用,所以如果行为相同,我会尝试。
答案 1 :(得分:1)
尝试:
package cef_debug;
import java.io.*;
public class Main {
public static void main(String[] args) throws Throwable {
String folder = args[0];
File[] files = (new File(folder)).listFiles();
String line;
for (int i = 0; i < files.length; i++) {
try {
BufferedReader br = new BufferedReader(new FileReader(files[i]));
while ((line = br.readLine()) != null) {
}
} finally {
try {
if (br != null){
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}