Почему 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 и т.д.