【问题标题】:Read file in Scala : Stream closed在 Scala 中读取文件:流已关闭
【发布时间】:2017-03-20 12:15:32
【问题描述】:

我尝试像这样在 scala 中读取文件:

def parseFile(filename: String) = {
  val source = scala.io.Source.fromFile(filename)
  try {
    val lines = source.getLines().map(line => line.trim.toDouble)
    return lines
  } catch {
    // re-throw exception, but make source source is closed
    case
      t: Throwable => {
      println("error during parsing of file")
      throw t
    }
  } finally {
    source.close()
  }
}

当我稍后访问结果时,我得到一个

java.io.IOException: Stream Closed

我知道这是因为source.getLines() 只返回一个(惰性)Iterator[String],并且我已经关闭了finally 子句中的BufferedSource

如何避免此错误,即如何在关闭源之前“评估”流?

编辑:我试图打电话给source.getLines().toSeq,但没有帮助。

【问题讨论】:

  • 你可以返回一个列表而不是一个迭代器。只需return lines.toList
  • @marstran 我尝试了 toSeq,但它不起作用(运行时类型仍然是 Stream)。使用 toList,它可以工作,谢谢

标签: scala


【解决方案1】:

也许,您可以尝试以下解决方案,它可以使代码更具功能性并利用惰性求值。

首先,定义一个辅助函数using,它负责打开/关闭文件。

def using[A <: {def close() : Unit}, B](param: A)(f: A => B): B =
    try f(param) finally param.close()

然后,你可以用函数式编程风格重构你的代码:

using(Source.fromFile(filename)) {
  source =>
    val lines = Try(source.getLines().map(line => line.trim.toDouble))
    val result = lines.flatMap(l => Try(processOrDoWhatYouWantForLines(l)))
    result.get
}

其实using函数可以用来处理所有需要在操作结束时关闭的资源。

【讨论】:

  • 仅供参考的匿名特征将导致反射查找,这可能会影响性能。你可以使用java.lang.AutoClosable
【解决方案2】:

列表不懒,所以改变:

val lines = source.getLines().map(line => line.trim.toDouble)

val lines = source.getLines().toList.map(line => line.trim.toDouble)

为了强制计算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-28
    • 2014-04-25
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多