scala - Scala最终阻止关闭/刷新资源

标签 scala

有没有更好的方法来确保资源被正确释放—编写以下代码的更好方法?

        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/

相关文章:

scala - 为什么 Scala 选项的 foreach 比 get 更好?

scala - 为什么 Promise 不能是协变的

json - 如何将内存中的 JSON 字符串读入 Spark DataFrame

scala - 带状态的函数式监听器

scala - Scala枚举和readResolve

json - 无法使用 Scala circle json 库中 LocalDateTime 的自定义解码器反序列化对象

java - 集群中 Akka 成员(actor)查找

scala - 在scala中警告或避免整数除法(导致截断)

scala - 函数式根据 Scala 中的值创建列表

scala - scala 项目的 Maven 编译回复 'No sources to compile'