narutow
V2EX  ›  Java

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

  •  
  •   narutow · Mar 12, 2021 · 4368 views
    This topic created in 1899 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
        1
    JadeLove  
       Mar 12, 2021
    用 try-with-resources
    zpf124
        2
    zpf124  
       Mar 12, 2021
    一般都是 close 抛异常不怎么处理,甚至错误打印有时候都没有。

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


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

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

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

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

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