2012-04-18 9 views
5

Chcę napisać program w języku Java, który uruchamia zewnętrzne polecenie "java myprog < input.txt> output.txt". Ostatecznym celem jest uruchomienie tej komendy na dwóch różnych programach i porównanie ich podobieństwa wyjściowego z ich odpowiednimi plikami wyjściowymi.Program w języku Java, który uruchamia zewnętrzny plik "java myprog < input.txt > output.txt"

Wydaje mi się, że przeczytałem prawie każdy artykuł o użyciu ProcessBuilder do uruchomienia zewnętrznego programu i kilka wpisów dotyczących obsługi danych wprowadzanych przez użytkownika w tym zewnętrznym programie, ale nadal nie mogę sprawić, żeby wszystko działało. Z tego, co przeczytałem, myślę, że najlepszym podejściem jest nie uruchamiać dokładnie powyższego polecenia, ale zamiast tego odczytać plik input.txt i podać go bajt po bajcie do obiektu Process, a następnie zebrać dane wyjściowe i zapisać je na wyjście .txt ... Jestem w 100% otwarty na inne opcje.

Połączyłem poniższy kod na podstawie moich odczytów. Wygląda na to, że poprawnie podaje dane wejściowe z pliku input.txt do myprog, ale kiedy próbuję wydrukować dane wyjściowe zewnętrznego programu na konsolę, aby je zweryfikować, program zawiesza się w miejscu, w którym oczekuje się (niespodziewanie) danych wejściowych od użytkownika w myprogu.

Otrzymuję te same problemy z linkiem redirectErrorStream (true) i bez niego.

Naprawdę chcę, żeby to było w Javie, ponieważ planuję udostępnić kod źródłowy ludziom, których wyniki programu będę porównywać, i są głównie zaznajomieni z Javą.

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 

} 

Oto treść 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(); 
    } 
} 

a plik input.txt tylko

p 

Plik output.txt powinny być

Hello world! 
Enter something: 
+0

Co masz na myśli przez wprowadzenie danych użytkownika? Czy możesz pokazać swój myprog lub przynajmniej jego najbardziej odpowiednie części? Jeśli chcesz uzyskać lepszą pomoc, postępuj zgodnie z konwencjami nazewnictwa Java. Używanie niestandardowych nazw (w tym niepisywanie wielkich liter nazw pierwszych liter) powoduje, że kod jest mylący. –

+2

Odpowiedziałem na to jakiś czas temu .. http://stackoverflow.com/questions/3062305/executing-shell-commands-from-java/3062874#3062874 – dsmith

+0

@HovercraftFullOfEels: Dodałem treść myprog.java do opisu. Przepraszam, że nie dodawano wielkich liter do nazwy klasy. – missthang

Odpowiedz

0

Czy myślisz o użyciu Runtime.getRuntime() .exec() zamiast?

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

Nie ma to żadnej przewagi nad używaniem ProcessBuilder. –

+0

Nadal wisi w ten sam sposób. – missthang

+0

Zostawiłem w moim przykładzie "<" and ">", czy dodałeś te? @Hovercraft ... 1 wiersz kodu vs 10 jest zawsze zaletą w mojej książce, ale dla każdego z nich. – user282172

0

Możesz dołączyć słoik "myprog" i samodzielnie wywołać metodę main(). Tym bardziej, że jeśli myprog znajduje się w twojej domenie, możesz całkowicie pozbyć się głównej metody.

4

Zastanawiam się, czy twój problem polega częściowo na tym, że nie używasz osobnych wątków do odczytu danych wejściowych i wyjściowych. Na przykład:

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

To wszystko! Działa doskonale z przełącznikiem classpath z polecenia java. Dziękuję bardzo!!!!! – missthang

+0

@missthang: Cieszę się, że to działa. –

Powiązane problemy