Как надежно читать и писать в работающий внешний процесс из Java?

Я хотел бы иметь возможность порождать внешний процесс из Java, периодически писать на его вход и читать ответ, как если бы это была консоль. Однако большую часть времени, когда я читаю вывод процесса, ничего не доступно. Есть ли хорошая практика, чтобы делать такие вещи (даже избегать этого)?

Вот урезанный пример того, что не работает:

import org.apache.commons.exec.*;
import java.io.*;
//...
CommandLine cl = CommandLine.parse("/usr/bin/awk {print($1-1)}");
System.out.println(cl.toStrings());
Process proc = new ProcessBuilder(cl.toStrings()).start();
OutputStream os = proc.getOutputStream(); // avoiding *Buffered* classes
InputStream is = proc.getInputStream();   // to lessen buffering complications
os.write(("4" + System.getProperty("line.separator")).getBytes());
os.flush(); // Doesn't seem to flush.
// os.close(); // uncommenting works, but I'd like to keep the process running
System.out.println("reading");
System.out.println(is.read()); // read even one byte? usually is.available() -> 0

Странно, если я оберну OutputStream в BufferedWriter, я смогу читать из некоторых процессов (cat), но не из других (awk, grep).

1 ответ

Как правило, принятый подход является правильным. Несколько вещей, хотя:

  1. InputStream.read() это метод блокировки. Он ожидает ввода и не загружает процессор. Вы должны вращаться вокруг этого...
  2. Можно прочитать более одного байта, просто используйте read(byte[] buffer, int offset, int len)
  3. Обтекание входных потоков в BufferedInputStream облегчает доступ (readLine() метод). Это альтернатива BufferedReader.
  4. Не забудьте использовать Process.waitFor(),

Также убедитесь, что внешний процесс записывает в стандартный вывод (а не в стандартную ошибку). Две возможности здесь:

  1. использование Process.getErrorStream() (и относиться к нему как к другому InputStream)
  2. измените командную строку на /usr/bin/awk {print($1-1)} 2>&1, Это перенаправит стандартную ошибку на стандартный вывод.
Другие вопросы по тегам