我试图设计一个包装器,以便在 java 中调用命令行实用程序时使用。runtime.exec() 的问题在于,您需要不断地从进程中读取数据和错误流,否则它会在填充缓冲区时挂起。这导致我进行以下设计:
public class CommandLineInterface {
private final Thread stdOutThread;
private final Thread stdErrThread;
private final OutputStreamWriter stdin;
private final History history;
public CommandLineInterface(String command) throws IOException {
this.history = new History();
this.history.addEntry(new HistoryEntry(EntryTypeEnum.INPUT, command));
Process process = Runtime.getRuntime().exec(command);
stdin = new OutputStreamWriter(process.getOutputStream());
stdOutThread = new Thread(new Leech(process.getInputStream(), history, EntryTypeEnum.OUTPUT));
stdOutThread.setDaemon(true);
stdOutThread.start();
stdErrThread = new Thread(new Leech(process.getErrorStream(), history, EntryTypeEnum.ERROR));
stdErrThread.setDaemon(true);
stdErrThread.start();
}
public void write(String input) throws IOException {
this.history.addEntry(new HistoryEntry(EntryTypeEnum.INPUT, input));
stdin.write(input);
stdin.write("\n");
stdin.flush();
}
}
和
public class Leech implements Runnable{
private final InputStream stream;
private final History history;
private final EntryTypeEnum type;
private volatile boolean alive = true;
public Leech(InputStream stream, History history, EntryTypeEnum type) {
this.stream = stream;
this.history = history;
this.type = type;
}
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line;
try {
while(alive) {
line = reader.readLine();
if (line==null) break;
history.addEntry(new HistoryEntry(type, line));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我的问题是 Leech 类(用于“提取”进程和错误流并将它们输入到历史记录中 - 这就像一个日志文件) - 一方面阅读整行很好而且很容易(以及我目前的做),但这意味着我错过了最后一行(通常是提示行)。我只在执行下一个命令时看到提示行(因为在那之前没有换行符)。另一方面,如果我自己阅读字符,我如何判断该过程何时“完成”?(完成或等待输入)有没有人尝试过自进程的最后输出以来等待 100 毫秒并声明它“完成”之类的事情?
关于我如何围绕诸如 runtime.exec("cmd.exe") 之类的东西实现一个好的包装器有什么更好的想法吗?