最后使用Scala异常捕获关闭流

lis*_*sak 3 io scala exception

有人知道这个问题的解决方案吗?我重写了try catch,最后构建了一个功能性的做事方式,但我现在无法关闭流:-)

import scala.util.control.Exception._
def gunzip() = {
  logger.info(s"Gunziping file ${f.getAbsolutePath}")
  catching(classOf[IOException], classOf[FileNotFoundException]).
    andFinally(println("how can I close the stream ?")).
    either ({
        val is = new GZIPInputStream(new FileInputStream(f))
        Stream.continually(is.read()).takeWhile(-1 !=).map(_.toByte).toArray
      }) match {
          case Left(e) =>
            val msg = s"IO error reading file ${f.getAbsolutePath} ! on host ${Setup.smtpHost}"
            logger.error(msg, e)
            MailClient.send(msg, msg)
            new Array[Byte](0)
          case Right(v) => v
        }
  }
Run Code Online (Sandbox Code Playgroud)

我根据Senia的解决方案重写了这个:

def gunzip() = {
  logger.info(s"Gunziping file ${file.getAbsolutePath}")

  def closeAfterReading(c: InputStream)(f: InputStream => Array[Byte]) = {
    catching(classOf[IOException], classOf[FileNotFoundException])
      .andFinally(c.close())
      .either(f(c)) match {
      case Left(e) => {
        val msg = s"IO error reading file ${file.getAbsolutePath} ! on host ${Setup.smtpHost}"
        logger.error(msg, e)
        new Array[Byte](0)
      }
      case Right(v) => v
    }
  }

  closeAfterReading(new GZIPInputStream(new FileInputStream(file))) { is =>
    Stream.continually(is.read()).takeWhile(-1 !=).map(_.toByte).toArray
  }
}
Run Code Online (Sandbox Code Playgroud)

sen*_*nia 5

对于这种情况,我更喜欢这种结构:

def withCloseable[T <: Closeable, R](t: T)(f: T => R): R = {
  allCatch.andFinally{t.close} apply { f(t) }
}

def read(f: File) =
  withCloseable(new GZIPInputStream(new FileInputStream(f))) { is =>
    Stream.continually(is.read()).takeWhile(-1 !=).map(_.toByte).toArray
  }
Run Code Online (Sandbox Code Playgroud)

现在你可以用它包装Try并恢复一些例外:

val result =
  Try { read(f) }.recover{
    case e: IOException => recover(e) // logging, default value
    case e: FileNotFoundException => recover(e)
  }
val array = result.get // Exception here!
Run Code Online (Sandbox Code Playgroud)