我正在尝试使用Apache Commons exec解决与命令行过程的交互。我坚持下面的代码:
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream ins = new ByteArrayOutputStream();
OutputStreamWriter ow = new OutputStreamWriter(ins);
BufferedWriter writer = new BufferedWriter(ow);
ByteArrayInputStream in = new ByteArrayInputStream(ins.toByteArray());
PumpStreamHandler psh = new PumpStreamHandler(out, null, in);
CommandLine cl = CommandLine.parse(initProcess);
DefaultExecutor exec = new DefaultExecutor();
DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
exec.setStreamHandler(psh);
try {
exec.execute(cl, resultHandler);
int i = 0;
while (true) {
String o = out.toString();
if (!o.trim().isEmpty()) {
System.out.println(o);
out.reset();
}
// --- PROBLEM start ---
if (i == 3) {
writer.write(internalProcessCommand);
// string with or without trailing \n, both tested
writer.flush();
writer.close();
// tested even ins.write(internalProcessCommand.getBytes())
}
// --- PROBLEM end ---
Thread.sleep(3000);
i++;
}
} catch (ExecuteException e) {
System.err.println(e.getMessage());
}
我希望我的代码清楚。我连续阅读
out
并在清除流3秒后打印它。问题输入到in
,并传递给PumpStreamHandler
。我需要连续不断地从代码本身传递过程命令,就像通过CLI与过程进行交互一样。当我简单地使用System.in
作为PumpStreamHandler
参数时,我可以从控制台正常编写过程命令。如何通过代码传递字符串来获得相同的结果?编辑:
我还尝试连接从
PipedInputStream
接收数据的PipedOutputStream
,但是似乎只能在关闭PipedOutputStream
后才能读取数据,这使其无法重用,因此无法实现交互。编辑2:
解决了自己。解决方案如下。豪:-)
最佳答案
好的,我使用内置工具而非外部库解决了此问题。由于读取Process
'InputStream
的独立线程,我得以实现自己的目标:
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.start();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
StreamReader outputReader = new StreamReader(process.getInputStream(), System.out);
outputReader.start();
StreamReader err = new StreamReader(process.getErrorStream(), System.err);
err.start();
for (int i = 0; i < 3; i++) {
Thread.sleep(5000);
writer.write(internalProcessCommand + "\n");
writer.flush();
}
writer.write("exit\n");
writer.flush();
while (process.isAlive()) {
System.out.println("alive?");
Thread.sleep(100);
}
System.out.println("dead");
outputReader.shutdown();
err.shutdown();
StreamReader:
class StreamReader extends Thread {
private AtomicBoolean running = new AtomicBoolean(false);
private InputStream in;
private OutputStream out;
public StreamReader(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
running.set(true);
}
@Override
public void run() {
Scanner scanner = new Scanner(in);
PrintWriter writer = new PrintWriter(out, true);
while (running.get()) {
if (scanner.hasNextLine()) {
writer.println(scanner.nextLine());
}
}
scanner.close();
}
public void shutdown() {
running.set(false);
}
}