这是一个我有疑问的例子(来自另一个SO问题):
public static void writeToFile (final String filename)
{
PrintWriter out = null;
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(filename);
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(fos, "UTF-8")));
for (final String line : log)
{
out.println(line);
}
out.flush();
out.close();
}
catch (final Exception e)
{
System.err.println("Unable to write log to file.");
}
finally
{
if (fos != null)
{
try
{
fos.close();
}
catch (final IOException e)
{
System.err.println("Unable to write log to file.");
}
}
}
}
现在我认为这段代码工作正常并释放所有应该使用的资源等等。我的问题是:
为什么要关闭FileOutputStream
的{{1}}部分中的finally
?当然,我可以在try-catch-finally
?
为什么我必须单独关闭try-catch
而不是简单地用FileOutputStream
替换new OutputStreamWriter(fos, ...
?如果我先关闭FileOutputStream,会自动关闭其余部分并释放资源吗?同样的问题适用于套接字,如果我关闭套接字连接会自动关闭流读取器/编写器并释放资源吗?
我一再被告知要确保我使用“UTF-8”读取和写入流,因为不同的系统具有不同的字符集(或沿着这些行的东西)。这是否仍然适用于读取/写入RAW字节数据(例如,来自非文本文件,或加密的结果),因为我认为charsets只与文本字符有关?
答案 0 :(得分:6)
因为如果你的代码抛出一个未处理的异常,那么try-catch bloc之后的代码段永远不会被执行。例如NullPointerExcpetion
就属于这种情况。
你不必。如果您关闭一个流,它的任何封闭流也将被关闭。
没有。仅在将字节转换为字符(或相反)时才是这种情况。您正在为OutputStreamWriter
指定字符集,该字符集负责将字符转换为字节。
答案 1 :(得分:1)
我为什么要关闭try-catch-finally的finally部分中的FileOutputStream?
您可以将close()
放在所有写入/读取操作块的末尾,但如果在那里出现问题(读/写),您将到达异常处理块,没有流将被关闭如果您选择将close()
放在异常处理块中并且一切正常,请猜猜是什么?...将不会关闭任何流。所以你可以在两个代码块中完成它,但这样代码的可读性就会降低。因此,将它放在finally块上可以确保它将以任何方式关闭。
其次,您应该只关闭已链接的最后一个流。所以,如果你有这个。
fos = new FileOutputStream(filename);
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(fos, "UTF-8")));
你只需要
out.close();
这将关闭与出口相关联的其他流。
UTF-8部分取决于您尝试读取的数据编码类型,如果您编码UTF-8,则解码UTF-8。
答案 2 :(得分:0)
在第一点 - 如果你的代码抛出错误而不是异常,如果close语句不在finally中,则不会关闭FileOutputStream。在你捕获异常时,你的情况有点人为,但是在更典型的情况下会捕获更具体的异常,除非你整理finally块中的资源,方法的执行可能会在它到达之前终止。将关闭资源的代码。
答案 3 :(得分:0)