narutow
V2EX  ›  Java

Java 读写 Stream 时, 如果 close 失败了, 应该怎样保证 Stream 最终会被关闭呢?

  •  
  •   narutow · Mar 12, 2021 · 4869 views
    This topic created in 2074 days ago, the information mentioned may be changed or developed.

    用下面的 java 代码读写流, 如果 close 发生了异常, 怎么保证流一定会被关闭呢? 还是说 close 都出错了, 那么就不管了, 直接挂掉?

    OutputStream out = null;
    try {
        out = new FileOutputStream("");
        // ...操作流代码
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (out != null) {
                out.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    17 replies  •  2021-03-13 16:32:39 +08:00
    JadeLove
    JadeLove
    Mar 12, 2021
    1
    用 try-with-resources
    zpf124
    zpf124
    Mar 12, 2021
    2
    一般都是 close 抛异常不怎么处理,甚至错误打印有时候都没有。

    因为 close 一般报错都是 流已经被关闭的错误。
    比如你在其他地方已经执行过一次 close 了或者流的另一端已经直接端口了。
    xiecanmy
    xiecanmy
    Mar 12, 2021
    3
    用 try-with-resources


    try(OutputStream out = new FileOutputStream("")) {

    // ...操作流代码
    } catch (Exception e) {
    e.printStackTrace();
    }
    Oktfolio
    Oktfolio
    Mar 12, 2021
    4
    try (OutputStream out = new FileOutputStream("")) {

    } catch (Exception e) {
    e.printStackTrace();
    }
    RedBeanIce
    RedBeanIce
    Mar 12, 2021
    5
    因为 finally 一定会执行。。。
    RedBeanIce
    RedBeanIce
    Mar 12, 2021❤️4
    6
    我错了。我傻子。请不要看我。
    narutow
    narutow
    OP
    Mar 12, 2021
    7
    @RedBeanIce 是的, 但如果写在 finally 中的 close 再抛异常, 说明 close 失败了, 这时候该怎么处理呢
    RedBeanIce
    RedBeanIce
    Mar 12, 2021❤️1
    8
    @narutow 请看 6 楼,我是傻子我是傻子我是傻子
    Still4
    Still4
    Mar 12, 2021
    9
    finally 最好只放最简单的逻辑,比如断开连接,直接变量置空,干净利落的切掉

    你这个例子里面,不得不调用可能抛出异常的代码,只能无视了,还能咋办呢....
    iseki
    iseki
    Mar 12, 2021 via Android
    10
    一般不处理吧,你不能无限兜底,另外如果 finally 里抛了异常会被抑制,见 suppress
    ychost
    ychost
    Mar 12, 2021
    11
    1. try-with-resource
    2. lombok @Clean
    当然都无法解决你说的问题,在 finally 里面 抛异常了,不能无限兜底的
    hantsy
    hantsy
    Mar 12, 2021
    12
    以为是 Stream API 。

    IO Stream 基本都是可以 Try (初始化 Stream ){},主要看它是否实现 Closable 接口。
    newmlp
    newmlp
    Mar 12, 2021
    13
    close 不可能失败的,
    Brentwans
    Brentwans
    Mar 12, 2021
    14
    大概明白你的疑问,你的问题应该是异常处理没弄明白。这里 close 失败的异常,是让处理后事用的。假设,你的输出流是将新增的内存数据持久化写到磁盘用的。close 关闭失败,意味着持久化失败了,这个时候可能的处理是将新增加的数据对象从内存删除,恢复到添加之前的样子。
    需要强制处理的异常,通常是处理后事用的,下层没处理最好还是抛出上层处理。二话不说默认异常输出到日志,这个代码会有问题的。
    cheng6563
    cheng6563
    Mar 12, 2021❤️1
    15
    IO Stream 的 close()的异常,基本上都不是关闭连接产生的异常而是重复关闭连接产生的。
    dreamist
    dreamist
    Mar 12, 2021❤️1
    16
    首先,try-with-resource 并不能解决这个问题,因为它本质上是编译器的语法糖,和自己写 try catch finally 一样的。然后关于这个问题,如果真的出现了 close 也也出现异常的情况,那么其实是没有什么好的办法的了,无法再确定它内部是不是真的关闭了的。
    ikas
    ikas
    Mar 13, 2021
    17
    假设 close 出错了,那这个错误可能会对将来的执行造成影响,这时候,错误还是会产生,还是有机会再见的~,这时候就会来检查,为啥关闭不了~,如果是业务有要求,那么关闭的时候出错,你必然是要做处理的,或者继续 throw
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1996 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 49ms · UTC 15:01 · PVG 23:01 · LAX 07:01 · JFK 10:01
    ♥ Do have faith in what you're doing.