在 Java 中关闭 In/OutputStream

Close In/OutputStream in Java

如你所见,我做了 close fooo,所以在那之后我做需要 close OutputStream 吗? :

public void writedata(List<sinhvien> svlist) {
    FileOutputStream fo = null;
    ObjectOutputStream oo = null;
    try {
        fo = new FileOutputStream(datasv);
        oo = new ObjectOutputStream (fo);
        oo.writeObject(svlist);
    }
    catch (IOException e) {}
    
    finally {
            try {
                fo.close();
                oo.close();
            }
            catch (IOException e ) {}
    }
}

类似于:... OutputStream os if (os != null ) try { os.close() } ... 有这个必要吗?

您可以对资源使用 try 并取消显式关闭调用 像

public void writeData(final List<Sinhvein> svList){
    try(final FileOutputStream fo = new FileOutputStream(datasv); final ObjectOutputStream oo = new ObjectOutputStream(fo);){
    // do something with fo and oo
    }
}

尝试使用资源的全部意义在于避免显式的 finally 块,这些块负责清理。

你的顺序错了。

允许流缓冲。通过首先关闭基础流 (fo),如果 oo 已缓冲,您的代码将失败。您还吃了任何异常,这显然是一个非常糟糕的主意:如果您的代码失败(例如, oo close 抛出异常,报告它未能写出最后几个字节,因为 fo 已经关闭,你永远不会知道,现在你有一个损坏的文件,却不知道它已损坏。

您可以关闭 oo 并完成它,但问题是,如果 oo = new ObjectOutputStream(fo) 失败怎么办?您仍然需要关闭 fo 然后。

教训:

  1. 您必须按堆栈顺序关闭您打开的每个资源(您最后做的事情需要先关闭)。
  2. 永远不要写一个空的 catch 块,除非你真的,真的,真的知道你在做什么。

应用这些课程的最佳方式:

  1. 使用 try-with-resources
  2. 随意乱扔throws IOException之类的东西在你的签名上。您的 main 应声明为 throws Exception。在不可行或不可能的情况下,正确的 'I do not know what happened' catch 块是:`catch (Thingie e) { throw new RuntimeException("uncaught", e);

因此:

public void writedata(List<sinhvien> svlist) throws IOException {
    try (var fo = new FileOutputStream(datasv);
         var oo = new ObjectOutputStream(fo)) {

        oo.writeObject(svlist);
    }
}

好几个数量级:

  1. 它没有缓存问题
  2. 更容易阅读和遵循
  3. 一个名为 'writeData' 的方法显然可以以以下替代方式退出: 嗯,糟糕,我将其保存到的 I/O 系统出现问题。方法应该抛出看起来很明显的东西,而 IOException 在这里很明显。
  4. 不会在保存数据失败时静默不做任何事情。