我有一个外部流程,我想将其视为一个函数String=>String.给定一行输入,它将以单行输出响应.看来我应该使用scala.sys.process,这显然是一个优雅的库,可以从scala中轻松访问许多shell操作.但是,我无法弄清楚如何执行这个简单的用例.
如果我向进程'stdin写一行,它会将结果打印在一行中.我如何使用sys.process创建包装器,以便我可以交互使用该过程?例如,如果我有一个实现ProcessWrapper,这是一个程序,它的输出:
// abstract definition
class ProcessWrapper(executable: String) {
def apply(line: String): String
}
// program using an implementation
val process = new ProcessWrapper("cat -b")
println(process("foo"))
println(process("bar"))
println(process("baz"))
Run Code Online (Sandbox Code Playgroud)
输出:
1 foo
2 bar
3 baz
Run Code Online (Sandbox Code Playgroud)
重要的是不要为每次调用重新加载进程,process因为存在重要的初始化步骤.
所以 - 在我发表评论之后 - 这将是我的解决方案
import java.io.BufferedReader
import java.io.File
import java.io.InputStream
import java.io.InputStreamReader
import scala.annotation.tailrec
class ProcessWrapper(cmdLine: String, lineListenerOut: String => Unit, lineListenerErr: String => Unit,
finishHandler: => Unit,
lineMode: Boolean = true, envp: Array[String] = null, dir: File = null) {
class StreamRunnable(val stream: InputStream, listener: String => Unit) extends Runnable {
def run() {
try {
val in = new BufferedReader(new InputStreamReader(this.stream));
@tailrec
def readLines {
val line = in.readLine
if (line != null) {
listener(line)
readLines
}
}
readLines
}
finally {
this.stream.close
finishHandler
}
}
}
val process = Runtime.getRuntime().exec(cmdLine, envp, dir);
val outThread = new Thread(new StreamRunnable(process.getInputStream, lineListenerOut), "StreamHandlerOut")
val errThread = new Thread(new StreamRunnable(process.getErrorStream, lineListenerErr), "StreamHandlerErr")
val sendToProcess = process.getOutputStream
outThread.start
errThread.start
def apply(txt: String) {
sendToProcess.write(txt.getBytes)
if (lineMode)
sendToProcess.write('\n')
sendToProcess.flush
}
}
object ProcessWrapper {
def main(args: Array[String]) {
val process = new ProcessWrapper("python -i", txt => println("py> " + txt),
err => System.err.println("py err> " + err), System.exit(0))
while (true) {
process(readLine)
}
}
}
Run Code Online (Sandbox Code Playgroud)
主要部分是 StreamRunnable,其中在线程中读取进程,并将接收到的行传递给“LineListener”(一个简单的 String => Unit - 函数)。主要只是一个示例实现 - 调用 python ;)
| 归档时间: |
|
| 查看次数: |
976 次 |
| 最近记录: |