9

我有下面的代码,它只是从一个文件夹中读取所有文件。此文件夹中有 20,000 个文件。该代码在本地文件夹 ( ) 上运行良好,但在读取大约 1,000 - 2,000 个文件后d:/files在网络路径 ( ) 上失败。//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]));
4

2 回答 2

3

某些 java 版本有一个记录在案的错误,并且某些文件打开时达到了 2035 的限制。您可能刚刚达到了这个限制。

从评论:

为了澄清这个问题,在win32系统上打开文件有三种方式:

1:使用Win32 API

2:使用MFC类框架库。

3:使用 C-Library API(open() 和 fopen())

除了第三个选项,即选项1和2,几乎没有打开文件数的限制。第三种方法被限制(由于我不知道的原因)只能打开大约。2035 个文件。这就是为什么 MS JVM 能够打开无限(实际上)文件,但 SUN JVM 在 2035 个文件之后失败(我猜它是使用第三种方法打开文件)。

现在,这是很久以前修复的一个老问题,但他们可能会在网络访问中使用相同的功能,但该错误仍然存​​在。

即使关闭句柄或流,windows 也应该能够打开 >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 调用之外的任何其他调用,所以我会尝试行为是否相同。

于 2012-11-15T18:04:54.347 回答
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();
                }
            }
        }
    }
}
于 2012-11-15T17:39:35.247 回答