【问题标题】:How to stream stdout in Scala?如何在 Scala 中流式传输标准输出?
【发布时间】:2016-06-28 23:19:04
【问题描述】:

基本上,我有一个输出到标准输出的程序。我正在我的 Scala 代码中运行该程序。我现在要做的是将输出重定向到文件。像这样。

val cmd = progName + " " + arguments 
cmd #> new java.io.File(outputFilePath) !

我还必须稍后处理该输出文件。这就是为什么这种方法很慢,因为我必须首先等待程序完成并将所有内容写入输出文件。我更喜欢流式传输标准输出的内容,以便在流式传输时从另一个线程读取内容。这样,我可以在我从 Scala 运行的程序运行时处理数据。

此外,输出文件中的数据由换行符分隔。有没有办法,可以在程序运行的时候逐行获取数据。

最后,Java 中有什么东西可以做到这一点,然后我也可以在 Scala 中使用它吗?

【问题讨论】:

  • 看看 Scala ProcessBuilder 看看如何重定向标准输出
  • 我对 Scala 的了解还不够,无法确定,但这可能是 this 的副本。

标签: java scala apache-spark


【解决方案1】:

ProcessBuilder 有一个lineStream 方法,我认为它完全符合您的要求。它返回一个Stream[String],让您在输出可用时对其进行处理。

这是一个简单的程序,输出速度很慢,我保存为slow-printer.scala

// slow-printer.scala
for (i <- 1 to 10) {
  println(i)
  Thread.sleep(1000)
}

您可以像这样从程序中流式传输输出(每秒 1 行):

import scala.sys.process._

val lines = "scala slow-printer.scala".lineStream

lines foreach println

如果您坚持使用 2.10,或者如果您的输出不是换行符分隔,那么您可以使用 ProcessIO 来处理输出:

import scala.sys.process._

Seq("scala", "slow-printer.scala").run(new ProcessIO(
  _.close(), // stdin
  out => { // stdout
    val src = scala.io.Source.fromInputStream(out)
    for (line <- src.getLines()) {
      println(line)
    }
  },
  _.close() // stderr
))

【讨论】:

  • “val lines = ....”和“lines foreach println”在这里并行运行吗?
  • 是的,子进程与在主 Scala 程序中打印的行并行运行。试试看!您会看到每秒打印一行。
  • 这需要哪个版本的 Scala?因为我收到以下错误, :38: error: value lineStream is not a member of String val lines = "./my-cmd.sh".lineStream ^ :34: error: value foreach不是 Int 行的成员 foreach println
  • 我提供的文档链接是针对当前稳定版本的,即 2.11.8。我正在运行 2.11.7。
  • 啊,我明白了。还有其他方法可以处理这个问题,应该是 2.10 兼容的。我已经更新了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-03
  • 1970-01-01
  • 2020-11-25
  • 2022-11-12
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
相关资源
最近更新 更多