让 Stream 打开有什么问题?

What's wrong with leaving a Stream open?

在阅读有关 Java 的初学者书籍时,我了解到流一旦不再需要就必须始终关闭。为什么会这样?打开它有什么问题?

考虑以下示例:

 import java.io.*;
 public class SOStreamTest {

public static void main(String[] args){

    try{

        FileWriter writer = new FileWriter("Foo.txt");
        writer.write("hello foo!");
        //Writer.close();         <-!Line in Question -->
        }catch(IOException ex){
            ex.printStackTrace();
        }
}
}

如预期的那样出现警告消息,'resource leak: "writer" is never closed.'

你知道在你的 Windows PC 上你尝试删除一个文件但它正在被另一个程序使用吗?这就是为什么您应该始终关闭文件输入或输出流的原因之一。

这次 Linux 的另一个例子是,每个文件输入或输出流都需要称为文件句柄的东西。给定的 linux 系统将只允许存在一定数量的文件句柄,如果达到最大值,可能会发生不好的事情。

当您关闭流时,文件句柄被释放。

其他输入和输出流可能会导致类似的问题,例如,无法关闭网络流可能会使与另一台机器的连接保持打开状态。执行此操作几千次,你将 运行 端口不足或杀死你正在连接的机器。

一方面,您期望您的应用程序将在 main 的底部结束,但 main 是一个普通方法,可能会被继续到 运行 的其他代码调用。

您不希望流保留的原因是它们往往与 OS 资源相关联,这比内存更受限制。

套接字更麻烦,因为您可能会占用您的程序和远程主机的资源。

最常见的原因之一是确保所有内容都写入输出。

向我们的应用程序授予在文件中写入数据的权限可能需要一些时间。因此,为了避免每次写入单个字节时都请求它,我们使用像 BufferedWriter 这样的缓冲区来存储大部分数据,当它已满时,它会自动请求写入访问权限,写入其存储的数据,并且清理缓冲区。

但是在buffer未满,没有更多数据可写的情况下,我们需要显式通知buffer将数据写入文件。我们可以通过调用它的 flush 方法来完成,或者通过调用 close 方法来隐式调用 flush。没有它,我们的文件将不包含当前存储在缓冲区中的部分。

关掉你的直播的重要性可以归纳为两个一个要点s:

  • 首先,流通常与某些系统资源(套接字、文件、数据库连接)相关联,通常,将其作为昂贵的资产处理是一种很好的做法,因为它可能被其他进程共享甚至拖慢系统速度。

  • 此外,如果您不关闭流,它在内存中的表示将保持活动状态,因为没有提示告诉垃圾收集器可以删除该对象。

因此,通过关闭流,您可以明智地使用 系统资源 和进程的内存 space

编辑:正如下面的评论部分所指出的,我所说的关于垃圾收集的内容是错误的。但是,可能会发生这样的情况,即流可能会在被 GC 销毁之前关闭,因为许多基本流(至少在 Java 中)在其 finalize() 方法中包含对 close() 的调用。请参阅关于这个主题的SO thread