Reputation: 21589
Basically, I have a program whose output goes to stdout. I am running that program from within my Scala code. 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. In this way, I can process the data while the program I am running from Scala is running.
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?
Upvotes: 3
Views: 9908
Reputation: 33019
The ProcessBuilder has a lineStream
method, which I think does exactly what you want. It returns a Stream[String]
that lets you process the output as it becomes available.
Here's a simple program with slow output for testing, which I saved as 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:
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:
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
))
Upvotes: 5