【问题标题】:Running a java program from another java program从另一个 java 程序运行一个 java 程序
【发布时间】:2013-02-19 13:32:37
【问题描述】:

我正在开发一个简单的 java 程序。它只是编译并执行另一个 java 程序。我正在使用 Runtime.exec() 函数来编译和运行。编译没有问题。但是当它运行时,如果第二个程序需要一个输入来从键盘读取,我不能从主进程中给它。我使用了 getOutputStream() 函数。但这无济于事。我会提供我的代码。

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

这是我的主程序(sam.java)。

以下是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));

    }  
}  

没有问题,如果我的第二个程序只有打印语句。但是当我必须从其他人那里读到一些东西时,问题就出现了。

【问题讨论】:

  • 你必须做一些从 sam 的标准输入到 sam2 的管道,但这可能比它的价值更麻烦。
  • 请学习java命名约定并遵守它们,这里:类名应该以大写字母开头。
  • 我试图展示一个简单的例子。谢谢你的建议.. :)

标签: java runtime runtime.exec


【解决方案1】:

这有点奇怪,但你可以运行第二个程序而不用分叉它。只需调用其中的主要方法。所以忘记运行时部分并执行此操作:

sam2.main(new String[0]);

当然这样你必须在编译时编译sam2

【讨论】:

  • 我无法理解你所说的这句话是什么意思..!! :(
  • 它有效.. :) 非常感谢.. 但是当我使用这种方式时.. 整个控件将转到第二个程序。所以master只有在第二个程序完成后才会执行..我应该使用线程来解决这个问题吗..??
  • 问题..!!!当我将第二个程序的类名存储到字符串变量时,它遇到以下错误.. 找不到符号 tempfile.main(new String[0]); symbol: method main(String []) 位置:String 类型的变量临时文件 我该怎么办..??
  • 你想要什么?您不能将 String 用作类实例。也许您应该对这项工作使用 java 反射。但通常不需要反思。
【解决方案2】:

每个进程都需要被允许运行和完成。为此,您可以使用Process#waitFor。同样,您需要同时使用该流程的任何输出。 waitFor 将阻塞,因此您需要使用 Thread 来读取输入(如果需要,将输出写入进程)

根据 java/class 文件的位置,您可能还需要指定一个起始文件夹,进程的执行可以从该文件夹开始。

使用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;
        }
    }
}

现在显然,您应该检查进程的返回结果,并且可能会产生更好的与进程交互的机制,但这是基本思想......

【讨论】:

    【解决方案3】:

    你可以只调用第二个类的 main 方法。 main 方法和其他静态方法一样。

    【讨论】:

      【解决方案4】:

      这对我有用:

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

      【讨论】:

        【解决方案5】:

        只需调用主类文件。例如,如果你的java类文件名是xyz.java,你可以在java swing应用程序中点击JButton来调用和执行相同的文件,代码是

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

        就是这样……

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-10
          • 2011-04-17
          • 1970-01-01
          相关资源
          最近更新 更多