2012-04-18 11 views
5

Quiero escribir un programa Java que ejecute un comando externo "java myprog < input.txt> output.txt". El objetivo final es ejecutar este comando en dos programas diferentes y comparar su similitud de salida con sus respectivos archivos de salida.Un programa Java que ejecuta un "java myprog externo < input.txt > output.txt"

Creo que he leído casi todos los artículos relevantes sobre el uso de ProcessBuilder para ejecutar un programa externo y las pocas entradas sobre cómo manejar la entrada del usuario en ese programa externo, pero todavía no puedo hacer que funcionen. Por lo que he leído, creo que el mejor enfoque es no ejecutar el comando exacto anterior, sino leer el archivo input.txt y alimentarlo byte a byte en el objeto Process, luego recopilar el resultado y escribirlo en la salida .txt ... Estoy 100% abierto a otras opciones.

He creado el siguiente código según mis lecturas. Parece alimentar correctamente la entrada de input.txt en myprog, pero cuando intento imprimir la salida del programa externo a la consola para verificar, el programa se cuelga en el punto donde se espera la entrada de usuario (sorpresa) en myprog.

Obtengo los mismos problemas con y sin la línea redirectErrorStream (verdadera).

Realmente quiero que esté en Java, ya que planeo compartir el código fuente con las personas cuyas salidas del programa compararé, y están principalmente familiarizadas con Java.

import java.io.*; 
import java.util.*; 

public class test7 { 

    public static void main(String args[]) { 

     try { 
      // WANT: "java myprog <input.txt> output.txt" 
      String inputFile = "input.txt"; 
      String outputFile = "output.txt"; 

      ProcessBuilder pb = new ProcessBuilder("java","myprog"); 
      pb.redirectErrorStream(true); // merge stdout, stderr of process 
      Process p = pb.start(); 

      // write input to the running program 
      OutputStream pos = p.getOutputStream(); 
      InputStream fis = new FileInputStream(inputFile); 
      int read = 0; 
      while ((read = fis.read()) != -1) { 
       pos.write(read); 
      } 
      fis.close(); 

      // get output of running program 
      InputStreamReader isr = new InputStreamReader(p.getInputStream()); 
      BufferedReader br = new BufferedReader(isr); 

      // HANGS HERE WHEN USER INPUT REQUIRED 
      String lineRead; 
      while ((lineRead = br.readLine()) != null) { 
       System.out.println(lineRead); 
      } 

     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } // end main 

} 

Aquí es el contenido del myprog.java:

import java.io.*; 

public class myprog { 

    public static void main(String args[]) throws IOException { 

     System.out.println("Hello world!"); 
     System.out.println("Enter something:"); 

     BufferedReader cin = new BufferedReader(new InputStreamReader(System.in)); 

     // the readLine() command causes ProcessBuilder to hang 
     cin.readLine(); 
    } 
} 

y el archivo entrada.txt es sólo

p 

El archivo debe ser salida.txt

Hello world! 
Enter something: 
+0

¿Qué quiere decir con la entrada del usuario requerida? ¿Puedes mostrar tu myprog o al menos las partes más pertinentes? Además, siga las convenciones de nomenclatura de Java si desea una mejor ayuda aquí. El uso de nombres no estándar (incluido el hecho de no poner en mayúscula las primeras letras de los nombres de las clases) hace que el código sea confuso. –

+2

Respondí esto hace un tiempo ... http://stackoverflow.com/questions/3062305/executing-shell-commands-from-java/3062874#3062874 – dsmith

+0

@HovercraftFullOfEels: Agregué el contenido de myprog.java a la descripción. Me disculpo por no capitalizar el nombre de la clase. – missthang

Respuesta

0

¿Has pensado en usar Runtime.getRuntime?() .exec() en su lugar?

Process proc = Runtime.getRuntime().exec("java myprog "+inputFile+" "+outputFile); 
+0

Esto no tiene ninguna ventaja sobre el uso de ProcessBuilder. –

+0

Todavía se cuelga de la misma manera. – missthang

+0

Me salí el "<" and ">" en mi ejemplo, ¿los agregó? @Hovercraft ... 1 línea de código vs 10 es siempre una ventaja en mi libro, pero cada uno es suyo. – user282172

0

Puede incluir el jar del 'myprog' y llamar al método main() usted mismo. Aún más si myprog está en su dominio, podría deshacerse por completo del método principal.

4

Me pregunto si su problema tiene que ver en parte con no usar hilos separados para leer la entrada y escribir la salida. Por ejemplo:

public static void main(String args[]) { 

     try { 
     // WANT: "java myprog <input.txt> output.txt" 
     String inputFile = "input.txt"; 
     String outputFile = "output.txt"; 

     // my ProcessBuilder Strings will be different from yours 
     ProcessBuilder pb = new ProcessBuilder("java", "-cp", ".;bin;", 
       "yr12.m04.a.MyProg"); 
     pb.redirectErrorStream(true); 
     Process p = pb.start(); 

     final OutputStream pos = p.getOutputStream(); 
     final PrintWriter pw = new PrintWriter(pos); 
     final InputStream fis = new FileInputStream(inputFile); 
     final BufferedReader fileBr = new BufferedReader(new InputStreamReader(fis)); 

     InputStreamReader isr = new InputStreamReader(p.getInputStream()); 
     final BufferedReader br = new BufferedReader(isr); 

     new Thread(new Runnable() { 
      public void run() { 
       String lineRead; 
       try { 
        while ((lineRead = br.readLine()) != null) { 
        System.out.println(lineRead); 
        } 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } finally { 
        if (br != null) { 
        try { 
         br.close(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
        } 
       } 
      } 
     }).start(); 

     new Thread(new Runnable() { 
      public void run() { 
       try { 
        String lineRead; 
        while ((lineRead = fileBr.readLine()) != null) { 
        pw.println(lineRead); 
        } 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } finally { 
        if (pw != null) { 
        pw.close(); 
        } 
        if (fileBr != null) { 
        try { 
         fileBr.close(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
        } 
       } 
      } 
     }).start(); 

     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
    } // end main 
+0

¡Eso es todo! Funciona perfectamente con el modificador de classpath desde el comando java. ¡¡¡¡¡Muchas gracias!!!!! – missthang

+0

@missthang: me alegra que lo hayas hecho funcionar. –

Cuestiones relacionadas