简体   繁体   English

如何在Scala中流式输出stdout?

[英]How to stream stdout in Scala?

Basically, I have a program whose output goes to stdout. 基本上,我有一个程序,其输出将输出到stdout。 I am running that program from within my Scala code. 我正在我的Scala代码中运行该程序。 What I do right now is to redirect the output to a file. 我现在要做的是将输出重定向到文件。 Something like this. 这样的事情。

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

I also have to later process that output file. 我还必须稍后处理该输出文件。 That is why this approach is slow, as I have to first wait for the program to have finished and everything written to the output file. 这就是为什么这种方法很慢的原因,因为我必须首先等待程序完成并将所有内容写入输出文件。 What I would prefer is to have content of the stdout being streamed so that from another thread I could read the contents as they are being streamed. 我更希望的是流式输出stdout的内容,以便在流式传输时可以从另一个线程读取内容。 In this way, I can process the data while the program I am running from Scala is running. 这样,我可以在从Scala运行的程序运行时处理数据。

Moreover, the data in the output file is delimited by newlines. 此外,输出文件中的数据由换行符分隔。 Is there a way, I could get the data line by line as the program is running. 有没有办法,我可以在程序运行时逐行获取数据。

Lastly, is there something in Java to do that, which I can also then use in Scala? 最后,在Java中有什么可以做的,然后我也可以在Scala中使用?

The ProcessBuilder has a lineStream method, which I think does exactly what you want. ProcessBuilder有一个lineStream方法,我认为它确实可以实现您想要的功能。 It returns a Stream[String] that lets you process the output as it becomes available. 它返回一个Stream[String] ,让您在输出可用时对其进行处理。

Here's a simple program with slow output for testing, which I saved as slow-printer.scala : 这是一个简单的程序,用于测试输出缓慢,我将其保存为slow-printer.scala

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

You can stream the output (1 line per second) from the program like this: 您可以像这样通过流传输程序的输出(每秒1行):

import scala.sys.process._

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

lines foreach println

If you're stuck with 2.10, or maybe if your output isn't newline-delimited, then you can use ProcessIO to handle the output instead: 如果您坚持使用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
))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM