在回答了一些问题并阅读了一些评论后,实际上在文件I/O的关闭操作中,IOException从未被抛出。
是否存在调用Stream / Reader / Writer上的close方法实际上会引发IOException的情况?
如果确实抛出异常,应该如何处理?
在回答了一些问题并阅读了一些评论后,实际上在文件I/O的关闭操作中,IOException从未被抛出。
是否存在调用Stream / Reader / Writer上的close方法实际上会引发IOException的情况?
如果确实抛出异常,应该如何处理?
我发现了两种情况:
这两种情况都取决于在缓冲区仍有数据的情况下发生某些事情。Close刷新缓冲区后再关闭文件,因此如果写入数据到文件时出现错误,它会抛出一个IOException。
如果您执行以下代码并传递要在网络驱动器上创建的文件的名称,然后在按下回车键之前拔掉网络电缆,它将导致程序在close中抛出一个IOException。
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Test
{
public static void main(final String[] argv)
{
final File file;
file = new File(argv[0]);
process(file);
}
private static void process(final File file)
{
Writer writer;
writer = null;
try
{
writer = new FileWriter(file);
writer.write('a');
}
catch(final IOException ex)
{
System.err.println("error opening file: " + file.getAbsolutePath());
}
finally
{
if(writer != null)
{
try
{
try
{
System.out.println("Please press enter");
System.in.read();
}
catch(IOException ex)
{
System.err.println("error reading from the keyboard");
}
writer.close();
}
catch(final IOException ex)
{
System.err.println("See it can be thrown!");
}
}
}
}
}
从Java 7开始,您可以使用try-with-resources来摆脱这种混乱(删除了对close()
操作的显式异常生成代码):
private static void process(final File file) {
try (final Writer writer = new FileWriter(file)) {
writer.write('a');
} catch (final IOException e) {
// handle exception
}
}
这将自动处理close()
中的异常,并在内部执行显式null
检查。
IOException
一样处理,而不是像经常推荐的那样被忽略。我猜测的假设是,既然你已经使用完流,那么它是否被正确清理就无关紧要了。close()
操作引发异常,很可能涉及到刷新一些输出、提交某些事务(在你认为是只读的数据库连接的情况下),等等——绝对不应该被忽视。而且,由于这种情况很少发生,因此通过中止操作并没有显著影响应用程序的可靠性。特别是FileInputStream.close
,即使你的硬盘着火了也不会抛出异常。可能对于套接字输入也是一样的。对于输出流,您还可以刷新。直到最近[请参见时间戳]BufferedOutputStream
在flush
抛出异常时无法关闭底层流。
(@MaartenBodewes希望我指出API文档未规定FileInputStream.close
不会抛出异常。在发布此帖子时,通常省略了提到这与Sun JDK(现在称为Oracle JDK和OpenJDK)有关的条款。似乎Android曾经使用的一个名为Apache Harmony的晦涩的旧重新实现可能具有不同的行为。其他实现或OpenJDK版本也可能抛出异常。)