я пытаюсь придумать дизайн для оболочки для использования при вызове утилит командной строки в 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")?