有没有更好的方法来确保资源被正确释放—编写以下代码的更好方法?
val out: Option[FileOutputStream] = try {
Option(new FileOutputStream(path))
} catch {
case _ => None
}
if (out.isDefined) {
try {
Iterator.continually(in.read).takeWhile(-1 != _).foreach(out.get.write)
} catch {
case e => println(e.getMessage)
} finally {
in.close
out.get.flush()
out.get.close()
}
}
最佳答案
这样的事情是一个好主意,但我可以将其作为一种方法:
def cleanly[A,B](resource: => A)(cleanup: A => Unit)(code: A => B): Option[B] = {
try {
val r = resource
try { Some(code(r)) }
finally { cleanup(r) }
} catch {
case e: Exception => None
}
}
(请注意,我们只捕获一次;如果您确实希望在一种情况下打印一条消息,而不是在另一种情况下打印,则您确实必须像您一样捕获两种消息)。 (还要注意,我只捕获异常;捕获
Error
通常也是不明智的,因为几乎不可能从中恢复。)该方法的用法如下:cleanly(new FileOutputStream(path))(_.close){ fos =>
Iterator.continually(in.read).takeWhile(_ != -1).foreach(fos.write)
}
由于它返回一个值,因此如果在这里成功(您可以忽略),您将得到一个
Some(())
。编辑:为了使它更通用,我真的希望它返回一个
Either
,以便您得到异常。像这样:def cleanly[A,B](resource: => A)(cleanup: A => Unit)(code: A => B): Either[Exception,B] = {
try {
val r = resource
try { Right(code(r)) } finally { cleanup(r) }
}
catch { case e: Exception => Left(e) }
}
现在,如果您收到
Right
,一切就OK了。如果收到Left
,则可以选择异常。如果您不关心该异常,则可以使用.right.toOption
将其映射到一个选项中,或者仅使用.right.map
或任何可以对正确结果进行操作的东西(只有Option
一样)。 (模式匹配是处理Either
的有用方法。)
关于scala - Scala最终阻止关闭/刷新资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8865754/