2013-03-05 26 views
7

Pracuję nad prostym programem java. Po prostu kompiluje i wykonuje inny program java. Używam funkcji Runtime.exec() do kompilowania i uruchamiania. Nie ma problemu z kompilacją. ale gdy zostanie uruchomiony, jeśli drugi program potrzebuje danych wejściowych do odczytu z klawiatury, nie mogę go przekazać z głównego procesu. Użyłem funkcji getOutputStream(). ale to nie mogło pomóc. Podam mój kod.Uruchamianie programu java z innego programu java

public class sam { 
    public static void main(String[] args) throws Exception { 
     try { 
      Process p = Runtime.getRuntime().exec("javac sam2.java"); 
      Process p2 = Runtime.getRuntime().exec("java sam2"); 
      BufferedReader in = new BufferedReader( 
           new InputStreamReader(p2.getInputStream())); 

      OutputStream out = p.getOutputStream(); 
      String line = null; 
      line = in.readLine(); 
      System.out.println(line); 
      input=input+"\n"; 
      out.write(input.getBytes()); 
      p.wait(10000); 
      out.flush(); 
     }catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

To jest mój program główny (sam.java).

Poniżej znajduje się kod sam2.java

public class sam2 { 
public static void main(String[] args) throws Exception { 

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    String str; 
    System.out.println("Enter the number..\n"); 
    str = br.readLine(); 
    System.out.println(Integer.parseInt(str)); 

    } 
} 

Nie ma problemu, jeśli mój drugi program ma tylko sprawozdania z drukowaniem. Ale problem powstaje, gdy muszę przeczytać coś od drugiego.

+0

musiałbyś zrobić jakiś rodzaj fajki ze STDIN sam do sam2, ale to może być więcej kłopotu niż jego wartość. –

+0

Proszę nauczyć się konwencji nazewnictwa java i trzymać się ich, tutaj: nazwy klas powinny rozpoczynać się wielką literą. – kleopatra

+0

Próbowałem przedstawić prosty przykład. dzięki za twoją radę .. :) – BBHeeMAA

Odpowiedz

18

To trochę dziwne, ale możesz uruchomić drugi program bez jego rozwidlania. Po prostu wywołanie głównej metody. Więc zapomnij sekcję wykonania i to zrobić:

sam2.main(new String[0]); 

Oczywiście w ten sposób trzeba kompilować sam2 w czasie kompilacji

+0

Nie mogłem zrozumieć, co masz na myśli przez to oświadczenie .. !! :( – BBHeeMAA

+1

To działa .. :) dziękuję bardzo .. Ale kiedy używam w ten sposób .. cała kontrola zniknie do drugiego programu. więc master zostanie wykonany dopiero po zakończeniu drugiego programu. Czy powinienem użyć wątków, aby rozwiązać ten problem .. ?? – BBHeeMAA

+0

Oczywiście powinieneś. –

1

Możesz po prostu zadzwonić główną metodę drugiej klasie. Główna metoda jest podobna do każdej innej metody statycznej.

9

Każdy proces musi mieć możliwość uruchomienia i zakończenia. W tym celu można użyć Process#waitFor. Podobnie, musisz zużywać dowolne dane wyjściowe z procesu w tym samym czasie. waitFor będzie blokować, więc będziesz potrzebować użyć Thread do odczytu wejścia (i jeśli musisz, wypisz wyjście do procesu)

W zależności od lokalizacji pliku Java/Class, może być konieczne określenie początkowego folder, z którego można rozpocząć wykonywanie procesu.

Większość to znacznie łatwiejsze przy użyciu ProcessBuilder

import java.io.File; 
import java.io.IOException; 
import java.io.InputStream; 

public class CompileAndRun { 

    public static void main(String[] args) { 
     new CompileAndRun(); 
    } 

    public CompileAndRun() { 
     try { 
      int result = compile("compileandrun/HelloWorld.java"); 
      System.out.println("javac returned " + result); 
      result = run("compileandrun.HelloWorld"); 
     } catch (IOException | InterruptedException ex) { 
      ex.printStackTrace(); 
     } 
    } 

    public int run(String clazz) throws IOException, InterruptedException {   
     ProcessBuilder pb = new ProcessBuilder("java", clazz); 
     pb.redirectError(); 
     pb.directory(new File("src")); 
     Process p = pb.start(); 
     InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream()); 
     consumer.start(); 

     int result = p.waitFor(); 

     consumer.join(); 

     System.out.println(consumer.getOutput()); 

     return result; 
    } 

    public int compile(String file) throws IOException, InterruptedException {   
     ProcessBuilder pb = new ProcessBuilder("javac", file); 
     pb.redirectError(); 
     pb.directory(new File("src")); 
     Process p = pb.start(); 
     InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream()); 
     consumer.start(); 

     int result = p.waitFor(); 

     consumer.join(); 

     System.out.println(consumer.getOutput()); 

     return result;   
    } 

    public class InputStreamConsumer extends Thread { 

     private InputStream is; 
     private IOException exp; 
     private StringBuilder output; 

     public InputStreamConsumer(InputStream is) { 
      this.is = is; 
     } 

     @Override 
     public void run() { 
      int in = -1; 
      output = new StringBuilder(64); 
      try { 
       while ((in = is.read()) != -1) { 
        output.append((char) in); 
       } 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
       exp = ex; 
      } 
     } 

     public StringBuilder getOutput() { 
      return output; 
     } 

     public IOException getException() { 
      return exp; 
     } 
    } 
} 

Teraz oczywiście, należy sprawdzić wyniki Powrót procesów i może być produkować lepszy mechanizm interakcji z procesami, ale to podstawowa idea. ..

Powiązane problemy