2013-03-05 25 views
7

Sto lavorando su un semplice programma java. Compila semplicemente ed esegue un altro programma java. Sto usando la funzione Runtime.exec() per compilare ed eseguire. Non ci sono problemi con la compilazione. ma quando gira, se il secondo programma ha bisogno di un input per leggere dalla tastiera, non posso darlo dal processo master. Ho usato la funzione getOutputStream(). ma non poteva aiutare. Fornirò il mio codice.Esecuzione di un programma java da un altro programma 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(); 
     } 
    } 
} 

Questo è il mio programma principale (sam.java).

Quello che segue è il codice di 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)); 

    } 
} 

non c'è nessun problema, se il mio secondo programma ha solo dichiarazioni di stampa. Ma il problema sorge quando devo leggere qualcosa dall'altra.

+0

si dovrebbe fare una specie di pipe dallo STDIN di sam a sam2 ma questo potrebbe essere più difficile che valga la pena. –

+0

Si prega di imparare le convenzioni di denominazione java e attenersi ad esse, qui: i nomi delle classi dovrebbero iniziare con una lettera maiuscola. – kleopatra

+0

stavo cercando di presentare un semplice esempio. grazie per il tuo consiglio .. :) – BBHeeMAA

risposta

18

È un po 'strano ma è possibile eseguire il secondo programma senza biforcarlo. Basta chiamare il metodo principale in esso. Così dimenticare la sezione di runtime e fare questo:

sam2.main(new String[0]); 

Naturalmente in questo modo è necessario compilare sam2 al momento della compilazione

+0

non riuscivo a capire cosa vuoi dire con questa affermazione .. !! :( – BBHeeMAA

+1

Funziona .. :) grazie mille .. Ma quando uso in questo modo .. l'intero controllo andrà al secondo programma. così master eseguirà solo dopo il completamento del secondo programma .. dovrei usare i thread per risolvere questo problema .. ?? – BBHeeMAA

+0

Certo che dovresti. –

1

si può chiamare il metodo principale della seconda classe. Il metodo principale è come qualsiasi altro metodo statico.

9

Ogni processo deve essere autorizzato a funzionare e terminare. È possibile utilizzare Process#waitFor per questo scopo. Allo stesso tempo, è necessario consumare qualsiasi output dal processo allo stesso tempo. waitFor bloccherà quindi sarà necessario utilizzare un Thread per leggere l'input (e se è necessario, scrivere l'output per il processo)

A seconda della posizione del file java/class, potrebbe essere necessario specificare un avvio cartella da cui può iniziare l'esecuzione del processo.

La maggior parte di questo molto più facile usando 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; 
     } 
    } 
} 

Ora, ovviamente, si dovrebbe verificare i risultati di ritorno dei processi, e può essere produrre un meccanismo migliore per interagire con i processi, ma questo è l'idea di base. ..