scala Scala最终阻止关闭/刷新资源
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8865754/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala finally block closing/flushing resource
提问by Dzhu
Is there a better way to ensure resources are properly released - a better way to write the following code ?
有没有更好的方法来确保正确释放资源 - 编写以下代码的更好方法?
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()
}
}
采纳答案by Rex Kerr
Something like that is a good idea, but I'd make it a method:
像这样的想法是个好主意,但我会将其作为一种方法:
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
}
}
(note that we only catch once; if you really want a message printed in one case and not the other, then you do have to catch both like you did). (Also note that I only catch exceptions; catching Erroralso is usually unwise, since it's almost impossible to recover from.) The method is used like so:
(请注意,我们只捕获一次;如果您真的希望在一种情况下而不是另一种情况下打印消息,那么您必须像以前一样同时捕获两者)。(另请注意,我只捕获异常;捕获Error也通常是不明智的,因为几乎不可能从中恢复。)该方法的使用如下:
cleanly(new FileOutputStream(path))(_.close){ fos =>
Iterator.continually(in.read).takeWhile(_ != -1).foreach(fos.write)
}
Since it returns a value, you'll get a Some(())if it succeeded here (which you can ignore).
由于它返回一个值,Some(())如果它在这里成功,你会得到一个(你可以忽略它)。
Edit: to make it more general, I'd really have it return an Eitherinstead, so you get the exception. Like so:
编辑:为了使它更通用,我真的让它返回一个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) }
}
Now if you get a Right, all went okay. If you get a Left, you can pick out your exception. If you don't care about the exception, you can use .right.toOptionto map it into an option, or just use .right.mapor whatever to operate on the correct result only if it is there (just like with Option). (Pattern matching is a useful way to deal with Eithers.)
现在,如果你得到一个Right,一切都会好起来的。如果你得到Left,你可以挑选出你的例外。如果您不关心异常,则可以使用.right.toOption将其映射到选项中,或者仅使用.right.map或 仅当它存在时才对正确结果进行操作(就像 with Option)。(模式匹配是处理Eithers的有用方法。)
回答by Derek Wyatt
Have a look at Scala-ARM
This project aims to be the Scala Incubator project for Automatic-Resource-Management in the scala library ...
... The Scala ARM library allows users to ensure opening closing of resources within blocks of code using the "managed" method. The "managed" method essentially takes an argument of "anything that has a close or dispose method" and constructs a new ManagedResource object.
该项目旨在成为 Scala 库中自动资源管理的 Scala 孵化器项目......
... Scala ARM 库允许用户使用“托管”方法确保打开关闭代码块内的资源。“托管”方法本质上接受“任何具有 close 或 dispose 方法的东西”的参数,并构造一个新的 ManagedResource 对象。
回答by ChoppyTheLumberHyman
Alternatively you can do this with Choppy's Lazy TryClose monad.
或者,您可以使用 Choppy 的 Lazy TryClose monad 执行此操作。
val output = for {
fin <- TryClose(in)
fout <- TryClose.wrapWithCloser(new FileOutputStream(path))(out => {out.flush(); out.close();})
} yield wrap(Iterator.continually(fin.read).takeWhile(-1 != _).foreach(fout.get.write))
// Then execute it like this:
output.resolve
More info here: https://github.com/choppythelumberHyman/tryclose
更多信息在这里:https: //github.com/choppythelumberHyman/tryclose
(just be sure to import tryclose._and tryclose.JavaImplicits._)
(只要确保导入tryclose._和tryclose.JavaImplicits._)

