Pregunta

Si comienzo un proceso a través de Java Generador de procesos clase, tengo acceso completo a los flujos de entrada, salida y error estándar de ese proceso como Java InputStreams y OutputStreams.Sin embargo, no puedo encontrar una manera de conectar sin problemas esas transmisiones a System.in, System.out, y System.err.

Es posible utilizar redirectErrorStream() para conseguir un solo InputStream que contiene la salida estándar y el error estándar del subproceso, y simplemente recorrerlo y enviarlo a través de mi salida estándar, pero no puedo encontrar una manera de hacerlo y permitir que el usuario escriba en el proceso, como podría hacerlo si usé la C system() llamar.

Esto parece ser posible en Java SE 7 cuando salga; solo me pregunto si hay una solución alternativa ahora.Puntos de bonificación si el resultado de isatty() en el proceso hijo lleva a cabo la redirección.

¿Fue útil?

Solución

Necesitará copiar el Proceso flujos de salida, error y entrada a las versiones del sistema.La forma más sencilla de hacerlo es utilizando el IOUtils clase del paquete Commons IO.El método de copia Parece ser lo que necesitas.Las invocaciones del método de copia deberán realizarse en subprocesos 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();

Otros consejos

Una variación de la respuesta de John que compila y no requiere que uses 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 usa lo 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();

}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top