Вот удобный вспомогательный метод, который я часто использую. Я нахожу, что это приятно загромождает мой код.
def closer [T, C <: Closeable] (c : C) (f : C => T) : T =
try f (c)
finally c.close
Использовать его очень просто. В приведенном ниже примере используется входной поток из URLConnection. Конечно, вместо connection.getInputStream вы можете создать любой произвольный поток (или, в более общем случае, любой произвольный закрываемый объект).
val bytes = closer (connection.getInputStream) { istream =>
val bytes = new ByteArrayOutputStream ()
val buffer : Array [Byte] = new Array (1024)
Iterator.continually (istream read buffer).takeWhile (_ > 0).foreach (bytes write (buffer, 0, _))
bytes.toByteArray
}
Эта версия будет работать с любым методом close (не нужно реализовывать Closeable или что-либо еще).
def autoClose[R <: {def close()}, T](resource: R)(use: R => T): T = {
try use(resource)
// Don't want an NPE here masking an exception from use.
finally Option(resource).foreach(_.close())
}
Вот некоторые неявные классы для выполнения этой работы.
implicit class AutoCloseBracket[R <: Closeable](resource: R) {
def autoClose[V](use: R => V): V = try use(resource) finally resource.close()
}
implicit class AutoCloseableBracket[R <: AutoCloseable](resource: R) {
def autoClose[V](use: R => V): V = try use(resource) finally resource.close()
}