我刚刚使用了Java文件系统API,并编写了以下函数,用于复制二进制文件。原始代码来源于网络,但我添加了try/catch/finally语句以确保,在发生错误时,缓冲流将在退出函数前关闭(因此,我的操作系统资源得到释放)。
我简化了函数以显示其模式:
public static void copyFile(FileOutputStream oDStream, FileInputStream oSStream) throw etc...
{
BufferedInputStream oSBuffer = new BufferedInputStream(oSStream, 4096);
BufferedOutputStream oDBuffer = new BufferedOutputStream(oDStream, 4096);
try
{
try
{
int c;
while((c = oSBuffer.read()) != -1) // could throw a IOException
{
oDBuffer.write(c); // could throw a IOException
}
}
finally
{
oDBuffer.close(); // could throw a IOException
}
}
finally
{
oSBuffer.close(); // could throw a IOException
}
}
据我所知,我不能将两个
close()
放在finally子句中,因为第一个close()
可能会抛出异常,那么第二个就不会被执行。我知道C#有Dispose模式,可以使用
using
关键字处理此问题。我甚至更了解C++代码,可能是这样的(使用类似Java的API):
void copyFile(FileOutputStream & oDStream, FileInputStream & oSStream)
{
BufferedInputStream oSBuffer(oSStream, 4096);
BufferedOutputStream oDBuffer(oDStream, 4096);
int c;
while((c = oSBuffer.read()) != -1) // could throw a IOException
{
oDBuffer.write(c); // could throw a IOException
}
// I don't care about resources, as RAII handle them for me
}
我是否遗漏了什么,或者我真的必须在Java中编写丑陋而臃肿的代码才能处理缓冲流的
close()
方法中的异常吗?(请告诉我我哪里错了...)
编辑:是我还是在更新此页面时,我看到问题和所有答案在几分钟内都减少了一分?有人在享受匿名的乐趣吗?
编辑2:McDowell提供了一个非常有趣的链接,我觉得我不得不在这里提到: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html 编辑3:根据McDowell的链接,我发现Java 7提出了一种类似于C# using模式的模式:http://tech.puredanger.com/java7/#resourceblock。我的问题被明确描述。显然,即使使用Java 7的
do
,问题仍然存在。
oDBuffer
的分配应该放在外部的try
语句中。这表明这种做法是多么不方便。 - Nicola Musatti