Java 如何正确处理close()中的IOException
Java I/O类Java 如何正确处理close()中的IOException,java,file-io,error-handling,ioexception,Java,File Io,Error Handling,Ioexception,Java I/O类Java.io.Reader,Java.io.Writer,Java.io.InputStream,Java.io.OutputStream及其各种子类都有一个close()方法,可以抛出IOException 对于处理此类例外情况的适当方式是否有任何共识 我经常看到一些建议,建议只是默默地忽略它们,但这感觉是错误的,至少在打开资源进行写入的情况下,关闭文件时出现问题可能意味着无法写入/发送未刷新的数据 另一方面,在阅读参考资料时,我完全不清楚为什么close()会抛出它,以及
Java.io.Reader
,Java.io.Writer
,Java.io.InputStream
,Java.io.OutputStream
及其各种子类都有一个close()
方法,可以抛出IOException
对于处理此类例外情况的适当方式是否有任何共识
我经常看到一些建议,建议只是默默地忽略它们,但这感觉是错误的,至少在打开资源进行写入的情况下,关闭文件时出现问题可能意味着无法写入/发送未刷新的数据
另一方面,在阅读参考资料时,我完全不清楚为什么close()
会抛出它,以及如何处理它
那么有什么标准的建议吗
一个相关的问题是,但这更多的是关于哪些实现真正抛出异常,而不是关于如何处理异常
你真的不能对此做任何事情(例如写一些从错误中恢复的代码),但通常值得让别人知道
编辑:在进一步调查和阅读其他评论之后,我想说,如果你真的想处理它,那么你必须知道实现的细节。相反,您可能需要了解实现的细节,以决定是否需要处理它
但现实地说,我想不出任何流的例子,在这些流中,读或写操作可以正常工作而不引发异常,但是关闭会发生异常。在关闭writer之前尝试使用flush。关闭时出现异常的主要原因是其他一些资源可能正在使用数据,或者编写器/读取器可能根本没有打开。在关闭资源之前,请尝试查找资源是否已打开。首先,不要忘记将close()放在try-catch块的“finally”部分中。 其次,您可以用另一个try-catch异常包围close方法,并记录该异常。在大多数情况下,close()实际上不会抛出IOException。以下是代码: 关闭网络资源的错误实际上应该属于某种类型的
运行时异常
,因为在程序连接到网络资源后,您可以断开网络资源的连接
您可以看到一些使用Google代码搜索的/Writer和Streams的各种实现示例。BufferedReader和PipedReader实际上都不会抛出IOException,因此我认为您不必担心它,这基本上是安全的。如果您真的担心,您可以检查正在使用的库的实现,看看是否需要担心异常
像前面提到的其他人一样,除了记录IOException之外,您不能对IOException做太多事情
毕竟,finally
子句中的try/catch块非常难看
编辑:
进一步的检查揭示了IOException
的子类,如InterruptedIOException
、syncfailedeexception
、和ObjectStreamException
,以及从中继承的类。因此,仅仅捕获一个IOException
就太笼统了——除了记录信息之外,您不知道该如何处理它,因为它可能来自一系列错误
编辑2:
Urk,BufferedReader
是一个糟糕的例子,因为它将读取器
作为输入。我已将其更改为InputStream.java
但是,有一个带有InputStream
的层次结构,它取决于您要关闭的内容。例如,关闭StringWriter
不起任何作用。javadocs对此很清楚。在这种情况下,您可以忽略IOException,因为您知道它永远不会生成。从技术上讲,您甚至不需要调用close
/**
* Closing a <tt>StringWriter</tt> has no effect. The methods in this
* class can be called after the stream has been closed without generating
* an <tt>IOException</tt>.
*/
public void close() throws IOException {
}
/**
*关闭StringWriter无效。本文中的方法
*类可以在流关闭后调用,而无需生成
*一个例外。
*/
public void close()引发IOException{
}
对于其他流,根据需要记录并处理异常。通常,资源处理应如下所示:
final Resource resource = context.acquire();
try {
use(resource);
} finally {
resource.release();
}
在release
引发异常的(不太可能)情况下,use
引发的任何异常都将被丢弃。对于最接近接球手获胜的异常抛出,我没有任何问题。我相信JDK7(?)中的ARM块在这种情况下会做一些疯狂的事情,比如重新引用use
异常,并附加release
异常
如果使用executearound习惯用法,您可以将这些决定和潜在的混乱代码放在一个(或几个)位置。忽略或仅仅记录日志通常是个坏主意。即使您确实无法从中恢复,也应始终以统一的方式处理I/O异常,以确保您的软件以统一的方式运行
我至少建议如下处理:
//store the first exception caught
IOException ioe = null;
Closeable resource = null;
try{
resource = initializeResource();
//perform I/O on resource here
}catch(IOException e){
ioe = e;
}finally{
if (resource != null){
try{
resource.close();
}catch(IOException e){
if(null == ioe){
//this is the first exception
ioe = e;
}else{
//There was already another exception, just log this one.
log("There was another IOException during close. Details: ", e);
}
}
}
}
if(null != ioe){
//re-throw the exception to the caller
throw ioe;
}
上面的内容非常详细,但效果很好,因为它更喜欢在资源I/O期间使用IOException
,而不是在关闭期间使用,因为它更可能包含开发人员感兴趣的信息。当出现问题时,代码还将抛出一个IOException
,因此您可以获得一个统一的行为
也许有更好的方法,但你明白了
理想情况下,您应该创建一个新的异常类型,允许存储同级异常,因此如果您得到两个IOException
s,您可以同时存储它们
“忽略或仅仅记录日志通常是个坏主意。”这并没有回答问题。对于close()中的IOException,应该怎么做?仅仅是重复它只会把问题推得更高,甚至更难处理
理论
直接回答您的问题:当此IO操作失败时,根据具体情况,您可以
//store the first exception caught
IOException ioe = null;
Closeable resource = null;
try{
resource = initializeResource();
//perform I/O on resource here
}catch(IOException e){
ioe = e;
}finally{
if (resource != null){
try{
resource.close();
}catch(IOException e){
if(null == ioe){
//this is the first exception
ioe = e;
}else{
//There was already another exception, just log this one.
log("There was another IOException during close. Details: ", e);
}
}
}
}
if(null != ioe){
//re-throw the exception to the caller
throw ioe;
}