2010-09-20 6 views
10

He escrito el código java a continuación, que ejecuta otro programa java llamado "Newsworthy_RB".¿Cómo hacer un programa java para imprimir las instrucciones out.println() y err.println()?

Newsworthy_RB.java contiene las sentencias System.out.printlln() y System.err.println().

Deseo que ambas salidas se impriman en la consola del símbolo del sistema.

Lo que debe hacerse para obtener lo mismo.

El siguiente programa simplemente imprime las instrucciones out.println() y no las instrucciones err.println().

¿Desea saber si el siguiente código funcionará como esperaba?

command = "java -cp .:../sqljdbc.jar SetHash Newsworthy_RB"; 
Process child1 = Runtime.getRuntime().exec(command); 
InputStream in1 = child1.getErrorStream(); 
InputStream in2 = child2.getInputStream(); 
while ((c = in1.read()) != -1 || (c = in2.read()) != -1) { 
     System.out.print((char)c); 
    } 

Respuesta

14

En primer lugar, la forma preferida de iniciar programas externos es a través de ProcessBuilder. Incluso se menciona en the docs for Runtime:

ProcessBuilder.start() es ahora la mejor forma de iniciar un proceso con un entorno modificado.

En ProcessBuilder que tienen un método muy conveniente llamado redirectErrorStream: propiedad redirectErrorStream

Juegos de este proceso de constructor.

Si esta propiedad es verdad, entonces cualquier salida de error generado por subprocesos posteriormente iniciadas por inicio de este objeto() método se fusionará con la salida estándar, para que ambos puedan ser leídos mediante el Process.getInputStream () método. Esto facilita la correlación de los mensajes de error con la salida correspondiente. El valor inicial es falso.

Un ejemplo completo de cómo va a salir tanto el error estándar y salida estándar:

import java.io.*; 

public class Test { 
    public static void main(String... args) throws IOException { 

     ProcessBuilder pb = 
       new ProcessBuilder("java", "-cp", "yourClassPath", "HelloWorld"); 

     pb.redirectErrorStream(true); 
     Process proc = pb.start(); 

     Reader reader = new InputStreamReader(proc.getInputStream()); 
     int ch; 
     while ((ch = reader.read()) != -1) 
      System.out.print((char) ch); 
     reader.close(); 
    } 
} 

de respuesta a la actualización: No, el código con

while ((c = in1.read()) != -1 || (c = in2.read()) != -1) 

no lo hará trabajo, ya que read() es un método de bloqueo y solo tienes un hilo. Su única opción es usar un hilo por flujo de entrada, o (preferiblemente) fusionar los dos flujos de entrada en uno, usando ProcessBuilder.redirectErrorStream.

+0

Me encanta el tipo de explicación. Muchas gracias por su respuesta. Pero por el momento, hágame saber si la modificación que he hecho en mi pregunta funcionará o no. – LGAP

+0

Definitivamente implementaré los conceptos de ProcessBuilder en mis futuros procedimientos. – LGAP

+0

También avíseme 'ProcessBuilder pb = new ProcessBuilder (" java "," HelloWorld ");' ¿cómo mencionar el classpath del programa en esta declaración? – LGAP

10

Tiene que conectar la salida de ambas secuencias en hilos separados. Ejemplo de código de here:

Process p = Runtime.getRuntime().exec(cmd.array()); 
copyInThread(p.getInputStream(), System.out); 
copyInThread(p.getErrorStream(), System.err); 
p.waitFor(); 
return p.exitValue(); 

private void copyInThread(final InputStream in, final OutputStream out) { 
    new Thread() { 
     public void run() { 
      try { 
       while (true) { 
        int x = in.read(); 
        if (x < 0) { 
         return; 
        } 
        if (out != null) { 
         out.write(x); 
        } 
       } 
      } catch (Exception e) { 
       throw new RuntimeException(e); 
      } 
     } 
    } .start(); 
} 
+0

Gracias por su respuesta Mueller. He actualizado mi pregunta.Por favor, avíseme si funcionará o no. – LGAP

+3

De los documentos de 'Runtime':" ProcessBuilder.start() es ahora la forma preferida de iniciar un proceso con un entorno modificado. ". Recomiendo usar 'ProcessBuilder.redirectErrorStream'. (Vea mi respuesta.) – aioobe

+0

@aioobe: ¡Tiene razón! No sabía acerca de ProcessBuilder. –

1

Hay dos métodos en el procedimiento objeto: getErrorStream y getInputStream. Actualmente, su programa solo está escuchando uno. Querrá que escuche ambos.

Cuestiones relacionadas