2016-06-28 19 views
1

基本的に、出力がstdoutになるプログラムがあります。私はScalaコード内からそのプログラムを実行しています。私が今行っているのは、出力をファイルにリダイレクトすることです。このようなもの。Scalaでstdoutをストリームする方法は?

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

出力ファイルも後で処理する必要があります。そのため、このアプローチは遅いです。最初にプログラムが終了し、すべてが出力ファイルに書き込まれるのを待たなければなりません。私が好むのは、stdoutのコンテンツをストリーミングして、別のスレッドからストリーミング中のコンテンツを読むことができるようにすることです。このようにして、Scalaから実行しているプログラムが実行されている間にデータを処理することができます。

また、出力ファイルのデータは、改行で区切られます。方法はありますか、プログラムが実行されているときにデータを1行ずつ取得できます。

最後に、これを行うにはJavaに何かがありますが、これをScalaでも使用できますか?

+0

標準出力をリダイレクトする方法については、[ProcessBuilderを](http://www.scala-lang.org/api/current/index.html#scala.sys.process.ProcessBuilder)スカラ座で見てください – cchantep

+0

私はScalaについて十分に知ることはできませんが、これは[this](http://stackoverflow.com/a/5564667/1863564)の複製である可能性があります。 –

答えて

4

ProcessBuilderには、lineStreamメソッドがあります。これは、あなたが望むものとまったく同じだと思います。出力が利用可能になると出力を処理できるStream[String]を返します。あなたはこのようなプログラムからの出力(毎秒1行)をストリーミングできる

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

は、ここで私はslow-printer.scalaとして保存されたテストのために遅いの出力を持つ単純なプログラム、だ

import scala.sys.process._ 

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

lines foreach println 

出力が改行で区切られていない場合、または出力が改行で区切られていない場合は、代わりに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 
)) 
+0

"val lines = ...."と "lines foreach println"はここで並行して実行しますか? – pythonic

+0

はい、サブプロセスは、メインのScalaプログラムで印刷されている行と並行して実行されます。それを試してみてください!毎秒1行ずつ印刷されます。 – DaoWen

+0

これにはどのバージョンのScalaが必要ですか? :38:エラー:値lineStreamはStringのメンバーではありません。 val lines = "./my-cmd.sh".lineStream ^ :34:エラー:value foreach is Intのメンバーではありません lines foreach println – pythonic

関連する問題