web-dev-qa-db-fra.com

Exécution d'un programme Java à partir d'un autre programme Java

Je travaille sur un programme Java simple. Il compile et exécute simplement un autre programme Java. J'utilise la fonction Runtime.exec () pour compiler et exécuter. Il n'y a pas de problème avec la compilation. mais quand il est lancé, si le second programme a besoin d'une entrée pour lire à partir du clavier, je ne peux pas le donner à partir du processus maître. J'ai utilisé la fonction getOutputStream (). mais cela ne pouvait pas aider. Je vais fournir mon code.

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();  
        }  
    }  
}  

Ceci est mon programme principal (sam.Java).

Ce qui suit est le code de 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));

    }  
}  

Il n'y a pas de problème, si mon deuxième programme n'a que des états d'impression. Mais le problème se pose lorsque je dois lire quelque chose de l'autre.

10
BheeMa

C'est un peu étrange mais vous pouvez exécuter le deuxième programme sans le falsifier. J'appelle simplement la méthode principale. Alors oubliez la section d'exécution et procédez comme suit:

sam2.main(new String[0]);

Bien sûr, vous devez compiler sam2 au moment de la compilation

21
András Tóth

Chaque processus doit pouvoir s'exécuter et se terminer. Vous pouvez utiliser Process#waitFor à cette fin. De la même manière, vous devez utiliser n'importe quelle sortie du processus en même temps. waitFor bloquera donc vous aurez besoin d'utiliser une Thread pour lire l'entrée (et si vous en avez besoin, écrivez la sortie dans le processus)

Selon l'emplacement du fichier Java/class, vous devrez peut-être également spécifier un dossier de départ à partir duquel l'exécution du processus peut démarrer.

La plupart de ces choses sont beaucoup plus faciles avec 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;
        }
    }
}

Maintenant, évidemment, vous devriez vérifier les résultats de retour des processus, et peut-être produire un meilleur mécanisme pour interagir avec les processus, mais c'est l'idée de base ...

11
MadProgrammer

Vous pouvez simplement appeler la méthode principale de la deuxième classe. La méthode principale est comme n'importe quelle autre méthode statique.

1
Jay Q.

Appelez simplement le fichier de classe principal. Par exemple, si votre nom de fichier de classe Java est xyz.Java, vous pouvez appeler et exécuter la même chose dans une application Java Swing en cliquant sur un JButton, le code est

private void Btn_createdatabaseActionPerformed(Java.awt.event.ActionEvent evt) {                                                   
       xyz.main(new String[0]);
}

C'est tout...

0
Srinivasan. B

C'est ce qui a fonctionné pour moi:

try {
    single.main(new String[0]);
} catch (Exception e) {
    JOptionPane.showMessageDialog(null, e);
}
0
denis