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

2021-03-12 10:20:12 +08:00
 narutow

用下面的 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();
    }
}
3283 次点击
所在节点    Java
17 条回复
urzz
2021-03-12 10:28:46 +08:00
用 try-with-resources
zpf124
2021-03-12 10:29:02 +08:00
一般都是 close 抛异常不怎么处理,甚至错误打印有时候都没有。

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


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

// ...操作流代码
} catch (Exception e) {
e.printStackTrace();
}
Oktfolio
2021-03-12 10:35:40 +08:00
try (OutputStream out = new FileOutputStream("")) {

} catch (Exception e) {
e.printStackTrace();
}
RedBeanIce
2021-03-12 10:38:13 +08:00
因为 finally 一定会执行。。。
RedBeanIce
2021-03-12 10:38:46 +08:00
我错了。我傻子。请不要看我。
narutow
2021-03-12 10:39:11 +08:00
@RedBeanIce 是的, 但如果写在 finally 中的 close 再抛异常, 说明 close 失败了, 这时候该怎么处理呢
RedBeanIce
2021-03-12 10:46:55 +08:00
@narutow 请看 6 楼,我是傻子我是傻子我是傻子
Still4
2021-03-12 12:20:12 +08:00
finally 最好只放最简单的逻辑,比如断开连接,直接变量置空,干净利落的切掉

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

IO Stream 基本都是可以 Try (初始化 Stream ){},主要看它是否实现 Closable 接口。
newmlp
2021-03-12 14:59:02 +08:00
close 不可能失败的,
Brentwans
2021-03-12 15:44:42 +08:00
大概明白你的疑问,你的问题应该是异常处理没弄明白。这里 close 失败的异常,是让处理后事用的。假设,你的输出流是将新增的内存数据持久化写到磁盘用的。close 关闭失败,意味着持久化失败了,这个时候可能的处理是将新增加的数据对象从内存删除,恢复到添加之前的样子。
需要强制处理的异常,通常是处理后事用的,下层没处理最好还是抛出上层处理。二话不说默认异常输出到日志,这个代码会有问题的。
cheng6563
2021-03-12 17:41:36 +08:00
IO Stream 的 close()的异常,基本上都不是关闭连接产生的异常而是重复关闭连接产生的。
dreamist
2021-03-12 17:42:51 +08:00
首先,try-with-resource 并不能解决这个问题,因为它本质上是编译器的语法糖,和自己写 try catch finally 一样的。然后关于这个问题,如果真的出现了 close 也也出现异常的情况,那么其实是没有什么好的办法的了,无法再确定它内部是不是真的关闭了的。
ikas
2021-03-13 16:32:39 +08:00
假设 close 出错了,那这个错误可能会对将来的执行造成影响,这时候,错误还是会产生,还是有机会再见的~,这时候就会来检查,为啥关闭不了~,如果是业务有要求,那么关闭的时候出错,你必然是要做处理的,或者继续 throw

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/760928

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX