在Java中:从网络路径读取时出现“打开文件太多”错误

时间:2012-11-15 16:01:26

标签: java networking io

我有下面的代码,它只是读取文件夹中的所有文件。此文件夹中有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]));

2 个答案:

答案 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();
                }
            }
        }
    }
}