Stephen C..
53
如果您尝试从源头捕获并报告所有异常,则更好的解决方案是:
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(shapes);
oos.flush();
} catch (FileNotFoundException ex) {
// complain to user
} catch (IOException ex) {
// notify user
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException ex) {
// ignore ... any significant errors should already have been
// reported via an IOException from the final flush.
}
}
}
笔记:
标准的Java包装流,读者和作家的所有传播close和flush自己的包裹流等,所以你只需要关闭或刷新最外层的包装.
在try块结束时显式刷新的目的是使(实际)处理程序IOException能够看到任何写入失败1.
当您对输出流执行关闭或刷新时,由于光盘错误或文件系统已满而导致异常将被"抛出一个蓝月亮". 你不应该压制这个例外!.
如果你经常需要"关闭一个忽略IOExceptions的可能为空的流",那么你可以自己编写一个这样的辅助方法:
public void closeQuietly(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
// ignore
}
}
}
然后你可以用以下代码替换之前的finally块:
} finally {
closeQuietly(oos);
}
(另一个答案指出,一个closeQuietly方法已经在Apache Commons库中可用了......如果你不介意为你的项目添加10行方法的依赖项. 更新:请注意这些方法在版本2.6中不推荐使用API).
但请注意,您只能closeQuietly在IO异常真正无关的流上使用.
1 - 使用try-with-resources时不需要这样做.
论问题flush()与close()人们的询问:
标准的"过滤器"和"缓冲"输出流和close()写入器具有API合同,该合同声明会刷新所有缓冲的输出.您应该发现执行输出缓冲的所有其他(标准)输出类的行为方式相同.因此,对于标准类,flush()之前立即调用是多余的close().
对于自定义和第三方类,您需要进行调查(例如,阅读javadoc,查看代码),但任何close()不刷新缓冲数据的方法都可能被破坏.
最后,还有flush()实际问题.javadoc说的是这个(对OutputStream......)
如果该流的预期目的地是由底层操作系统提供的抽象,例如文件,则刷新流仅保证先前写入流的字节被传递到操作系统以进行写入; 它不能保证它们实际上写入物理设备,如磁盘驱动器.
所以...如果您希望/想象调用flush()保证您的数据将持续存在,那么您错了! (如果你需要做那种事情,看看FileChannel.force方法......)
另一方面,如果您可以使用Java 7或更高版本,则@Mike Clark的答案中描述的"新"试用资源是最佳解决方案.
如果您没有使用Java 7或更高版本来使用新代码,那么您可能陷入了深深的困境并深入挖掘.
从开始到结束,这似乎太脏了。Java真的很奇怪吗? (2认同)