如何关闭与 Source.fromFile("/tmp/foo").getLines() 返回的迭代器关联的流
how to close stream associated w/ iterator returned by Source.fromFile("/tmp/foo").getLines()
我需要使用 Source.getLines() 创建一个迭代器,并快速查看
Scala 源代码,在 运行ning 一些测试之后,迭代器似乎没有关闭
即使在迭代器耗尽之后(即在 hasNext() 开始为假之后)。
我想知道 Scala 为 closing/releasing 资源推荐的用于创建迭代器的技术是什么。我发现
一个有趣的库,似乎可以解决问题:
https://github.com/jsuereth/scala-arm
但是,我更愿意使用核心 scala 库而不是
如果可能的话,拉入第 3 方的东西。如果你感兴趣
在我如何测试这个(在 Linux 上使用 'lsof' 列出打开的文件),我的
代码如下:
object Test extends App {
import sys.process._
import scala.io.Source._
"echo hello world" #> new java.io.File("/tmp/testing") !
val src = fromFile("/tmp/testing")
val iter: Iterator[String] = src.getLines()
while (iter.hasNext) {
println("line=" + iter.next())
}
println("iterator exhausted.. sleeping while we check if file is still open using lsof")
Thread.sleep(200000)
}
在程序 运行ning 之后它还在休眠,运行 这个命令:
lsof | grep /tmp/testing
你可能会看到这样的输出:
java 15813 ...253,0.... 12 .. lots-of-othernumbers..0462 /tmp/testing
然后当程序终止时,grep 将变为空(如您所想)。
提前感谢您提供的任何提示!
这是我倾向于使用的模式:
def using[R <: Closeable, T](stream: R)(f: R => T): T =
try {
f(stream)
} finally {
stream.close()
}
你可以这样使用:
def readSomeLines(is: InputStream) = {
using(new BufferedReader(new InputStreamReader(is))) { stream =>
Iterator.continually(stream.readLine().takeWhile(_ != null)).foreach(println)
}
}
readSomeLines(new FileInputStream("/tmp/foo"))
基于之前的答案,我建议将声明资源(例如打开文件)和执行工作包装到 Scala Try 结构中:
def using[R <: Closeable, T](uri: String)(claimResource: String => R)(work: R => Try[T]): Try[T] = {
Try(claimResource(uri)) match {
case Success(resource) => try { work(resource) } finally { resource.close }
case Failure(f) => Failure(f)
}
}
def countLines(s: Source): Try[Int] =
Try(s.getLines().size)
def main(args: Array[String]): Unit = {
val fileName = """/path/to/file"""
using(fileName)(Source.fromFile(_))(countLines) match {
case Success(lc) => println(s"File '$fileName' has $lc lines")
case Failure(f) => println(s"Failure: $f")
}
}
我需要使用 Source.getLines() 创建一个迭代器,并快速查看 Scala 源代码,在 运行ning 一些测试之后,迭代器似乎没有关闭 即使在迭代器耗尽之后(即在 hasNext() 开始为假之后)。
我想知道 Scala 为 closing/releasing 资源推荐的用于创建迭代器的技术是什么。我发现 一个有趣的库,似乎可以解决问题:
https://github.com/jsuereth/scala-arm
但是,我更愿意使用核心 scala 库而不是 如果可能的话,拉入第 3 方的东西。如果你感兴趣 在我如何测试这个(在 Linux 上使用 'lsof' 列出打开的文件),我的 代码如下:
object Test extends App {
import sys.process._
import scala.io.Source._
"echo hello world" #> new java.io.File("/tmp/testing") !
val src = fromFile("/tmp/testing")
val iter: Iterator[String] = src.getLines()
while (iter.hasNext) {
println("line=" + iter.next())
}
println("iterator exhausted.. sleeping while we check if file is still open using lsof")
Thread.sleep(200000)
}
在程序 运行ning 之后它还在休眠,运行 这个命令:
lsof | grep /tmp/testing
你可能会看到这样的输出:
java 15813 ...253,0.... 12 .. lots-of-othernumbers..0462 /tmp/testing
然后当程序终止时,grep 将变为空(如您所想)。
提前感谢您提供的任何提示!
这是我倾向于使用的模式:
def using[R <: Closeable, T](stream: R)(f: R => T): T =
try {
f(stream)
} finally {
stream.close()
}
你可以这样使用:
def readSomeLines(is: InputStream) = {
using(new BufferedReader(new InputStreamReader(is))) { stream =>
Iterator.continually(stream.readLine().takeWhile(_ != null)).foreach(println)
}
}
readSomeLines(new FileInputStream("/tmp/foo"))
基于之前的答案,我建议将声明资源(例如打开文件)和执行工作包装到 Scala Try 结构中:
def using[R <: Closeable, T](uri: String)(claimResource: String => R)(work: R => Try[T]): Try[T] = {
Try(claimResource(uri)) match {
case Success(resource) => try { work(resource) } finally { resource.close }
case Failure(f) => Failure(f)
}
}
def countLines(s: Source): Try[Int] =
Try(s.getLines().size)
def main(args: Array[String]): Unit = {
val fileName = """/path/to/file"""
using(fileName)(Source.fromFile(_))(countLines) match {
case Success(lc) => println(s"File '$fileName' has $lc lines")
case Failure(f) => println(s"Failure: $f")
}
}