在 Java 中关闭 In/OutputStream
Close In/OutputStream in Java
如你所见,我做了 close fo 和 oo,所以在那之后我做需要 close OutputStream 吗? :
public void writedata(List<sinhvien> svlist) {
FileOutputStream fo = null;
ObjectOutputStream oo = null;
try {
fo = new FileOutputStream(datasv);
oo = new ObjectOutputStream (fo);
oo.writeObject(svlist);
}
catch (IOException e) {}
finally {
try {
fo.close();
oo.close();
}
catch (IOException e ) {}
}
}
类似于:... OutputStream os
if (os != null ) try { os.close() } ...
有这个必要吗?
您可以对资源使用 try 并取消显式关闭调用
像
public void writeData(final List<Sinhvein> svList){
try(final FileOutputStream fo = new FileOutputStream(datasv); final ObjectOutputStream oo = new ObjectOutputStream(fo);){
// do something with fo and oo
}
}
尝试使用资源的全部意义在于避免显式的 finally 块,这些块负责清理。
你的顺序错了。
允许流缓冲。通过首先关闭基础流 (fo
),如果 oo
已缓冲,您的代码将失败。您还吃了任何异常,这显然是一个非常糟糕的主意:如果您的代码失败(例如, oo
close 抛出异常,报告它未能写出最后几个字节,因为 fo 已经关闭,你永远不会知道,现在你有一个损坏的文件,却不知道它已损坏。
您可以关闭 oo
并完成它,但问题是,如果 oo = new ObjectOutputStream(fo)
失败怎么办?您仍然需要关闭 fo
然后。
教训:
- 您必须按堆栈顺序关闭您打开的每个资源(您最后做的事情需要先关闭)。
- 永远不要写一个空的 catch 块,除非你真的,真的,真的知道你在做什么。
应用这些课程的最佳方式:
- 使用 try-with-resources
- 随意乱扔
throws IOException
之类的东西在你的签名上。您的 main
应声明为 throws Exception
。在不可行或不可能的情况下,正确的 'I do not know what happened' catch 块是:`catch (Thingie e) { throw new RuntimeException("uncaught", e);
因此:
public void writedata(List<sinhvien> svlist) throws IOException {
try (var fo = new FileOutputStream(datasv);
var oo = new ObjectOutputStream(fo)) {
oo.writeObject(svlist);
}
}
好几个数量级:
- 它没有缓存问题
- 更容易阅读和遵循
- 一个名为 'writeData' 的方法显然可以以以下替代方式退出: 嗯,糟糕,我将其保存到的 I/O 系统出现问题。方法应该抛出看起来很明显的东西,而 IOException 在这里很明显。
- 不会在保存数据失败时静默不做任何事情。
如你所见,我做了 close fo 和 oo,所以在那之后我做需要 close OutputStream 吗? :
public void writedata(List<sinhvien> svlist) {
FileOutputStream fo = null;
ObjectOutputStream oo = null;
try {
fo = new FileOutputStream(datasv);
oo = new ObjectOutputStream (fo);
oo.writeObject(svlist);
}
catch (IOException e) {}
finally {
try {
fo.close();
oo.close();
}
catch (IOException e ) {}
}
}
类似于:... OutputStream os if (os != null ) try { os.close() } ... 有这个必要吗?
您可以对资源使用 try 并取消显式关闭调用 像
public void writeData(final List<Sinhvein> svList){
try(final FileOutputStream fo = new FileOutputStream(datasv); final ObjectOutputStream oo = new ObjectOutputStream(fo);){
// do something with fo and oo
}
}
尝试使用资源的全部意义在于避免显式的 finally 块,这些块负责清理。
你的顺序错了。
允许流缓冲。通过首先关闭基础流 (fo
),如果 oo
已缓冲,您的代码将失败。您还吃了任何异常,这显然是一个非常糟糕的主意:如果您的代码失败(例如, oo
close 抛出异常,报告它未能写出最后几个字节,因为 fo 已经关闭,你永远不会知道,现在你有一个损坏的文件,却不知道它已损坏。
您可以关闭 oo
并完成它,但问题是,如果 oo = new ObjectOutputStream(fo)
失败怎么办?您仍然需要关闭 fo
然后。
教训:
- 您必须按堆栈顺序关闭您打开的每个资源(您最后做的事情需要先关闭)。
- 永远不要写一个空的 catch 块,除非你真的,真的,真的知道你在做什么。
应用这些课程的最佳方式:
- 使用 try-with-resources
- 随意乱扔
throws IOException
之类的东西在你的签名上。您的main
应声明为throws Exception
。在不可行或不可能的情况下,正确的 'I do not know what happened' catch 块是:`catch (Thingie e) { throw new RuntimeException("uncaught", e);
因此:
public void writedata(List<sinhvien> svlist) throws IOException {
try (var fo = new FileOutputStream(datasv);
var oo = new ObjectOutputStream(fo)) {
oo.writeObject(svlist);
}
}
好几个数量级:
- 它没有缓存问题
- 更容易阅读和遵循
- 一个名为 'writeData' 的方法显然可以以以下替代方式退出: 嗯,糟糕,我将其保存到的 I/O 系统出现问题。方法应该抛出看起来很明显的东西,而 IOException 在这里很明显。
- 不会在保存数据失败时静默不做任何事情。