我想用scala替换我的很多perl.我倾向于做的很多事情之一就是调用二进制文件(通常是编译的C++,但可能是java,其他perl脚本,q脚本等),由我公司的其他团队提供给我.
例如,要做一些复杂的数学运算,我会启动一个外部二进制文件,然后将输入管道输入它.然后,我会收听其stdout流的结果,并stderr流式传输诊断消息.在perl中,我会使用POE::Wheel::Run小部件来完成此操作.我在scala中提出了类似(并且更好)的东西,但我想让它更强大.这是一个围绕ProcessIO物体的小包装.它看起来像这样:
class Exe(command: String, out: String => Unit, err: String => Unit) {
import scala.sys.process._
import scala.io._
import java.io._
import scala.concurrent._
val inputStream = new SyncVar[OutputStream];
val process = Process(command).run(
new ProcessIO(
stdin => inputStream.put(stdin),
stdout => Source.fromInputStream(stdout).getLines.foreach(out),
stderr => Source.fromInputStream(stderr).getLines.foreach(err)));
def write(s: String): Unit = synchronized {
inputStream.get.write((s + "\n").getBytes)
}
def close(): Unit = {
inputStream.get.close
}
}
Run Code Online (Sandbox Code Playgroud)
然后我会像这样使用它:
val exe = new Exe("tr [a-z] [A-Z]",
out => println("o: " + out),
err => println("e: " + err))
exe.write("lower")
exe.close()
Run Code Online (Sandbox Code Playgroud)
打印出来:
o: LOWER
Run Code Online (Sandbox Code Playgroud)
这让我获得90%,但是当进程退出时,最好是获得回调.它可能会退出,因为我已关闭输入流并且其内部循环停止,它可能会自行退出,或者它可能会退出,因为我已将其杀死.在回调中,最好知道它停止的原因和退出代码.
我对如何解决这个问题感到有点失落,任何帮助都会受到赞赏(对上述代码的任何编辑当然都是受欢迎的 - 我有点像菜鸟).
我正在使用2.9.0.1
Did*_*ont 10
您可以等待进程调用结束exitValue.您可以在单独的线程中执行此操作,其中将发生回调.也许上课Process可能是拉皮条的:
import scala.concurrent.ops.spawn
implicit def ProcessWithCallback(p: Process) {
def whenTerminatedDo(callback: Int => Unit) = spawn{
val exitValue = p.exitValue; callback(p)
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以随意使用它Exe.
Process由JVM提供并包含的类scala.sys.Process非常可行,很难不阻塞线程