Почему Scala Source не закрывает базовый InputStream?

Я использую Scala Source.fromFile, но я не могу найти хороший способ получить его close базовый InputStream после чтения файла.

Здесь мой код, который потерпит неудачу с AssertionError, потому что файл не может быть удален.

  def main(args : Array[String]) : Unit = {

    val myFile = new File("c:/tmp/doodah.txt")
    var src = Source.fromFile(myFile)
    src.getLines.foreach(l => print(l))

    val deleted: Boolean = myFile.delete

    assert (deleted , "File was not deleted - maybe the stream hasn't been closed in Source")

  }

У источника есть метод под названием reset, однако все, что это делает, это воссоздать источник из файла.

Внутренне Source создает базовый BufferedSource, который имеет метод close. Однако это не отображается из источника.

Я надеюсь, что Source выпустит дескриптор файла после того, как содержимое файла будет прочитано, но похоже, что это не так.

Лучшее обходное решение, которое я видел до сих пор, состоит в том, чтобы существенно отличить Source от BufferedSource и вызвать close.

try {
  src.getLines.foreach(l => print(l))
}
finally src match { case b: scala.io.BufferedSource => b.close }

В качестве альтернативы я мог бы создать Source из InputStream и управлять закрытием себя.

Однако это кажется несколько грязным. Как вы должны освобождать дескриптор файла при использовании Source?

Ответ 1

Scala.io._ - это баскетбольный взлом, созданный с единственной целью поддержки библиотеки XML и компилятора. Он плохо разработан и страдает множеством проблем. Scala 2.8 будет содержать улучшенную версию, хотя вряд ли что-нибудь о чем писать.

В настоящее время заинтересованные стороны прилагают усилия сторонних разработчиков для создания звуковой библиотеки ввода-вывода Scala. Он нацелен на извлечение уроков, извлеченных в результате редизайна ввода-вывода JDK7, предоставляя API Scala -ish.

Между тем... используйте библиотеки Java всякий раз, когда ваше приложение сталкивается с проблемами дизайна существующей библиотеки.

Ответ 2

Работает в Scala 2.8.x с небольшой модификацией. "getLines" → "getLines()"

...
src.getLines().foreach(l => print(l))
...

scala.io.Source в 2.8.x лучше продуман, чем его аналог в 2.7.x, и он правильно закрывает InputStream.

Ответ 3

насколько я могу сказать, что io.Source все еще сломан в 2.8 (соединения просачиваются и т.д.), поэтому людям следует отчаиваться от их использования.

Как предположил Дэвид, до тех пор, пока замена lib http://github.com/scala-incubator/scala-io не будет объединена (возможно, после 2.8), лучший выбор - java libs как apache commons-io и т.д.