【发布时间】:2010-03-17 15:19:23
【问题描述】:
我正在尝试设计一个包装器,以便在 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") 实现一个漂亮的包装器有什么更好的想法吗?
【问题讨论】:
标签: java command-line runtime.exec