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システムではファイルを開く3つの方法があります。

1:Win32APIの使用

2:MFCクラスフレームワークライブラリを使用します。

3:C-Library APIを使用する(open()およびfopen())

3番目のオプション、つまりオプション1と2を除いて、ファイルを開く数に実質的な制限はありません。3番目の方法は(私にはわからない理由で)約1つだけ開くように制限されています。2035ファイル。そのため、MS JVMは無制限の(実際には)ファイルを開くことができますが、SUN JVMは2035ファイルの後で失敗します(ファイルを開くために3番目の方法を使用していると思います)。

さて、これはかなり前に修正された古い問題ですが、バグがまだ存在する可能性があるネットワークアクセスで同じ機能を使用している可能性があります。

バグコメントのこのテストコードで示されているように、ハンドルまたはストリームを閉じなくても、ウィンドウは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 に答える