当重新使用FileOutputStream时,我应该关闭流吗?

4

正如标题所述,当重复使用FileOutputStream变量时,我是否应该关闭流?例如,在以下代码中,我是否应该在分配新文件之前调用outfile.close(),为什么?

谢谢:)

FileOutputStream outfile = null;
int index = 1;

while (true) {

    // check whether we should create a new file
    boolean createNewFile = shouldCreateNewFile();

    //write to a new file if pattern is identified
    if (createNewFile) {
        /* Should I close the outfile each time I create a new file?
        if (outfile != null) {
            outfile.close();
        }
        */
        outfile = new FileOutputStream(String.valueOf(index++) + ".txt");
    }

    if (outfile != null) {
        outfile.write(getNewFileContent());
    }

    if (shouldEnd()) {
        break;
    }
}

try {
    if (outfile != null) {
        outfile.close();
    }
} catch (IOException e) {
    System.err.println("Something wrong happens...");
}

1
“在我分配一个新文件之前” - 是的,您可以保留缓冲区中的更改,这意味着它们可能不会保存到文件中。您正在使用操作系统中有限的文件句柄资源。您正在占用JVM中的资源。您应该始终在使用后进行清理。请查看try-with-resources语句以获得处理可关闭资源的更好解决方案。 - MadProgrammer
3个回答

5
是的。 一旦您完成一个文件(流)的操作,您应该始终关闭它。这样,与该文件(流)分配的资源就会被释放到操作系统中,例如文件描述符,缓冲区等。

Java文档FileOutputStream.close()

关闭此文件输出流并释放与此流关联的任何系统资源。此文件输出流可能不再用于写入字节。

未关闭的文件描述符甚至可能导致java程序中的资源泄漏。参考资料


2
我认为这里的困惑在于“重用”FileOutputStream 的概念。你所做的只是重新使用一个标识符(即变量名称outfile),并将新值与其关联。但这只有对Java编译器有句法意义。被名称引用的对象-FileOutputStream只是被抛弃,最终将在未指定的时间点进行垃圾回收。你对曾经引用它的变量所做的任何操作都没有关系,无论是重新分配另一个FileOutputStream,将其设置为null还是让它超出范围。
显式调用close会将所有缓冲数据刷新到文件并释放相关资源。(虽然垃圾收集器也会释放它们,但你不知道这可能发生的时间。)请注意,close也可能抛出IOException,因此您需要知道试图执行该操作的时间点,您只有在明确调用函数时才能了解这一点。

2

即使没有自动资源管理或者 try-with-resources(见下文),你的代码也可以变得更加易读和可靠:

for (int index = 1; shouldCreateNewFile(); ++index) {
  FileOutputStream outfile = new FileOutputStream(index + ".txt");
  try {
    outfile.write(getNewFileContent());
  }
  finally {
    outfile.close();
  }
}

然而,Java 7引入了一种新的闭包语法,对于错误更加可靠和信息丰富。使用它,你的代码将如下所示:
for (int index = 1; shouldCreateNewFile(); ++index) {
  try (FileOutputStream outfile = new FileOutputStream(index + ".txt")) {
    outfile.write(getNewFileContent());
  }
}

输出流仍将被关闭,但是如果try块内部有异常,并且在关闭流时又有另一个异常,则该异常将被抑制(链接到主异常),而不是像前面的示例那样导致主异常被丢弃。

在Java 7或更高版本中,您应始终使用自动资源管理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接