stdout java
Iniciando un proceso con stdin/stdout/stderr heredado en Java 6 (3)
Si comienzo un proceso a través de la clase ProcessBuilder de Java, tengo acceso completo a las corrientes de error estándar, estándar y estándar de ese proceso como Java InputStreams
y OutputStreams
. Sin embargo, no puedo encontrar una forma de conectar esas transmisiones sin problemas a System.in
, System.out
y System.err
.
Es posible usar redirectErrorStream()
para obtener un solo InputStream
que contenga la salida estándar del subproceso y el error estándar, y simplemente recorrerlo y enviarlo a través de mi salida estándar, pero no puedo encontrar una manera de hacerlo y dejar que el usuario escriba en el proceso, como podría hacerlo si utilicé la llamada al system()
C system()
.
Esto parece ser posible en Java SE 7 cuando sale, solo me pregunto si hay una solución ahora. Puntos de bonificación si el resultado de isatty()
en el proceso hijo lleva a cabo la redirección.
Tendrá que copiar el Proceso fuera, errar, y las secuencias de entrada a las versiones del sistema. La forma más fácil de hacerlo es usar la clase IOUtils del paquete Commons IO. El método de copia parece ser lo que necesitas. Las invocaciones del método de copia deberán estar en hilos separados.
Aquí está el código básico:
// Assume you already have a processBuilder all configured and ready to go
final Process process = processBuilder.start();
new Thread(new Runnable() {public void run() {
IOUtils.copy(process.getOutputStream(), System.out);
} } ).start();
new Thread(new Runnable() {public void run() {
IOUtils.copy(process.getErrorStream(), System.err);
} } ).start();
new Thread(new Runnable() {public void run() {
IOUtils.copy(System.in, process.getInputStream());
} } ).start();
Una variación de la respuesta de John que compila y no requiere el uso de Commons IO:
private static void pipeOutput(Process process) {
pipe(process.getErrorStream(), System.err);
pipe(process.getInputStream(), System.out);
}
private static void pipe(final InputStream src, final PrintStream dest) {
new Thread(new Runnable() {
public void run() {
try {
byte[] buffer = new byte[1024];
for (int n = 0; n != -1; n = src.read(buffer)) {
dest.write(buffer, 0, n);
}
} catch (IOException e) { // just exit
}
}
}).start();
}
Para System.in
use el siguiente pipein()
lugar de pipe()
pipein(System.in, p.getOutputStream());
Implementación:
private static void pipein(final InputStream src, final OutputStream dest) {
new Thread(new Runnable() {
public void run() {
try {
int ret = -1;
while ((ret = System.in.read()) != -1) {
dest.write(ret);
dest.flush();
}
} catch (IOException e) { // just exit
}
}
}).start();
}