我开始并运行
Scala进程.
val dir = "/path/to/working/dir/"
val stockfish = Process(Seq("wine", dir + "stockfish_8_x32.exe"))
val logger = ProcessLogger(printf("Stdout: %s%n", _))
val stockfishProcess = stockfish.run(logger, connectInput = true)
该过程从标准IO(控制台)读取和写入.如果已经启动过程,如何向进程发送字符串命令?
Scala进程API具有ProcessBuilder,而ProcessBuilder又有许多有用的方法.但是在进程开始组成复杂的shell命令之前使用ProcessBuilder. Scala还有ProcessIO来处理输入或输出.我也不需要它.我只需要向我的进程发送消息.
在Java中我会做这样的事情.
String dir = "/path/to/working/dir/";
ProcessBuilder builder = new ProcessBuilder("wine", dir + "stockfish_8_x32.exe");
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
new Thread(() -> {
try {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("Stdout: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(5000); // it's just for example
writer.write("quit"); // send to the process command to stop working
writer.newLine();
writer.flush();
它运作得很好.我启动我的进程,从中获取InputStream和OutputStream,并使用流与进程交互.
似乎Scala Process trait没有提供写入它的方法.进程运行后,ProcessBuilder无用.而ProcessIO仅用于IO捕获和处理.
有没有办法写Scala运行过程?
更新:
我不知道如何使用ProcessIO将字符串传递给正在运行的进程.
我做了以下.
import scala.io.Source
import scala.sys.process._
object Sample extends App {
def out = (output: java.io.OutputStream) => {
output.flush()
output.close()
}
def in = (input: java.io.InputStream) => {
println("Stdout: " + Source.fromInputStream(input).mkString)
input.close()
}
def go = {
val dir = "/path/to/working/dir/"
val stockfishSeq = Seq("wine", dir + "/stockfish_8_x32.exe")
val pio = new ProcessIO(out, in, err => {})
val stockfish = Process(stockfishSeq)
stockfish.run(pio)
Thread.sleep(5000)
System.out.write("quit\n".getBytes)
pio.writeInput(System.out) // "writeInput" is function "out" which I have passed to conforming ProcessIO instance. I can invoke it from here. It takes OutputStream but where can I obtain it? Here I just pass System.out for example.
}
go
}
当然它不起作用,我无法理解如何实现上面的Java片段中的功能.很高兴有Scala代码的建议或片段清除我的问题.
最佳答案 我认为围绕Scala流程的文档(特别是ProcessIO的用法和语义)可以使用一些改进.我第一次尝试使用这个API时,我发现它非常令人困惑,并且需要一些试验和错误才能让我的子进程i / o正常工作.
我想看到一个简单的例子可能就是你真正需要的.我会做一些非常简单的事情:调用bc
作为子进程来进行一些简单的计算,然后将答案打印到我的标准输出.我的目标是做这样的事情(但是来自Scala,而不是来自我的shell):
$printf "1+2\n3+4\n" | bc
3
7
这是我在Scala中的表现:
import scala.io.Source
import scala.sys.process._
object SimpleProcessExample extends App {
def out = (output: java.io.OutputStream) => {
output.flush()
output.close()
}
def in = (input: java.io.InputStream) => {
println("Stdout: " + Source.fromInputStream(input).mkString)
input.close()
}
// limit scope of any temporary variables
locally {
val calcCommand = "bc"
// strings are implicitly converted to ProcessBuilder
// via scala.sys.process.ProcessImplicits.stringToProcess(_)
val calcProc = calcCommand.run(new ProcessIO(
// Handle subprocess's stdin
// (which we write via an OutputStream)
in => {
val writer = new java.io.PrintWriter(in)
writer.println("1 + 2")
writer.println("3 + 4")
writer.close()
},
// Handle subprocess's stdout
// (which we read via an InputStream)
out => {
val src = scala.io.Source.fromInputStream(out)
for (line <- src.getLines()) {
println("Answer: " + line)
}
src.close()
},
// We don't want to use stderr, so just close it.
_.close()
))
// Using ProcessBuilder.run() will automatically launch
// a new thread for the input/output routines passed to ProcessIO.
// We just need to wait for it to finish.
val code = calcProc.exitValue()
println(s"Subprocess exited with code $code.")
}
}
请注意,您实际上并不直接调用ProcessIO对象的任何方法,因为它们是由ProcessBuilder自动调用的.
这是结果:
$scala SimpleProcessExample
Answer: 3
Answer: 7
Subprocess exited with code 0.
如果您希望输入和输出处理程序与子进程之间进行交互,则可以使用标准线程通信工具(例如,两者都接近BlockingQueue
的实例).