2008-09-13 16 views
28

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, estándar y de proceso estándar 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.Iniciar un proceso con stdin/stdout/stderr heredado en Java 6

Es posible utilizar redirectErrorStream() para obtener un único InputStream que contiene la norma del subproceso y error estándar, y el bucle sólo a través de eso y enviarlo a través de mi nivel fuera, pero no puedo encontrar una manera de hacer eso y dejar el usuario escribe en el proceso, como podría hacerlo si usara la llamada C system().

Esto parece ser posible en Java SE 7 cuando sale, 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.

+0

Lo siento, no puedo ayudar. – jjnguy

+0

No hay problema. (Por cierto, yo no fui el que te votó negativamente). –

+0

Heh, bueno, gracias al tipo que me votó sin voto. Y gracias, John por no vengarme. – jjnguy

Respuesta

15

Tendrá que copiar el Process de salida, 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 copy method parece ser lo que necesita. Las invocaciones del método de copia deberán estar en hilos separados.

Aquí es 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(); 
+4

No del todo. IOUtils.copy toma InputStream como su primer argumento, por lo que no funcionará con getOutputStream. Por lo tanto, es IOUtils.copy (process.getInputStream(), System.out); Es un poco confuso, ya que getOutputStream realmente canaliza a la entrada del proceso. – Eelco

+0

La estructura de esto parece correcta, pero también estoy de acuerdo en que los parámetros de IOUtils parecen contraseñas. el process.getInputStream() es lo que se debe canalizar a stdout (sí, suena al revés). Entonces, aunque la estructura de esto se ve bien, las llamadas a IOUtils se ven mal y ahora me tienen un poco confundido ... – titania424

+1

Incorrecto. Esto simplemente ** canaliza datos entre las secuencias de entrada/salida del padre y del hijo, no le permite ** heredarlos **. Por ejemplo, incluso si el comando Java se inició en un terminal (C isatty() == true, o System.console()! = Null) el elemento secundario no se verá a sí mismo como ejecutado en un terminal, porque sus flujos de entrada/salida son pipas Esto es importante porque algunos (la mayoría) de los programas se comportan de manera diferente cuando se ejecutan en un terminal. El ProcessBuilder.Redirect.INHERIT de Java 7 funciona correctamente en este sentido. – Tobia

13

Una variación en la respuesta de Juan que compila y no requieren el uso de los Comunes 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(); 
} 
+0

No responde la pregunta para System.in. – solotim

+0

¿Por qué la tubería (System.in, process.getOutputStream()); no parece funcionar? –

3

Para System.in usa la siguiente pipein() en 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(); 

} 
+0

Esto no puede funcionar. –

Cuestiones relacionadas