Java中打开的文件太多

时间:2014-01-02 18:22:40

标签: java file jvm

我多次调用这种方法:

 private static void writeFile(double val, String myFile) throws IOException {
        FileWriter file = new FileWriter(myFile, true);
        file.write(val + "\n");
        file.close();
    }

在periode之后我有这个例外:

Exception in thread "main" java.io.FileNotFoundException: myFile (Too many open files)

我怎么能解决这个例外呢?

5 个答案:

答案 0 :(得分:4)

我猜你的文件写入中的一些(可能是全部)会导致异常,这会使file.close()短路。即使不是这种情况,通常的做法是将文件IO操作包装在try / catch / finally中,以确保无论读/写是否成功,您打开的任何内容都将被关闭。如果不关闭文件,则会用完句柄。

private static void writeFile(double val, String myFile) throws IOException {
    FileWriter file = null;
    try {
        file = new FileWriter(myFile, true);
        file.write(val + "\n");
    } catch( IOException e ) {
        e.printStackTrace();
    } finally {
        if( file != null ) {
            file.close();
        }
    }
}

或者,如果使用JDK 1.7:

private static void writeFile(double val, String myFile) throws IOException {
    try (FileWriter file = new FileWriter(myFile, true)) {
        file.write(val + "\n");
    } catch( IOException e ) {
        e.printStackTrace();
    }
}

答案 1 :(得分:1)

如前所述,由于某些IOException,关闭可能没有完成,所以在Java 7中:

private static void writeFile(double val, String myFile) throws IOException {
    try (FileWriter file = new FileWriter(myFile, true)) {
        file.write(val + "\n");
    }
}

问题出现了:代码是否隐藏了异常?

然而,真正的原因是您可能或多或少地同时写入同一文件。对于这种工作,记录器更适合。

使用java.util.logging:

private static void writeFile(double val, String myFile) throws IOException {
    Logger.getLogger(MyClass.class.getName()).log(Level.INFO, "" + val);
}

logging.properties中,您可以使用MyClass的文件记录器,并使用原样输出格式。

答案 2 :(得分:0)

我正在写机器上的1000000个文件,我没有收到任何错误。

import java.io.FileWriter;
import java.io.IOException;

public class ManyFiles {
    private static void writeFile(double val, String myFile) throws IOException {
        FileWriter file = new FileWriter(myFile, true);
        file.write(val + "\n");
        file.close();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 1000000; i++) {
            try {
                writeFile(i + 1.0, "/tmp/scratch/" + i);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

对我来说,所有文件都是生成的,没有失败:

$ ls /tmp/scratch | wc -l
1000000

您是否正在产生多个线程?

您必须详细了解您的环境:

  • 您使用的是哪种操作系统?
  • 您使用的是哪个JDK版本?
  • 什么是硬件配置?
  • 您运行此程序的用户是否有任何系统限制?

我的系统配置如下:

$ uname -a
Linux box01 3.11.8-300.fc20.x86_64 #1 SMP Wed Nov 13 16:34:27 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
$ javac -version
javac 1.7.0_45
$ java -version
java version "1.7.0_45"
OpenJDK Runtime Environment (fedora-2.4.3.0.fc20-x86_64 u45-b15)
OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)
$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 62970
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

答案 3 :(得分:0)

一个粗略的想法是每次打开文件时执行System.out.println()或写入日志文件,每次关闭它。当它崩溃时,查看日志是否打开而不关闭。
另一个考虑因素是如果你调用函数的速度快于它可以在文件上执行打开/关闭。在这种情况下,同步块可能对您的函数有用,以防止并发访问。

答案 4 :(得分:0)

当您打算使用任何外部资源并打开资源以开始使用时,请使用Java 7新功能尝试使用资源
这个新功能过于有用,因为您忘记在打开后关闭资源,它会在使用后自动关闭该资源。