我正在开发一个简单的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));
}
}
如果我的第二个程序只有打印语句,那没有问题。但当我必须从对方那里读一些东西时,问题就出现了。
这有点奇怪,但你可以运行第二个程序而不用分叉它。只需调用其中的main方法即可。所以忘记运行时部分并执行以下操作:
sam2.main(new String[0]);
当然这样你必须在编译时编译sam2
每个进程都需要被允许运行和完成。您可以使用
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;
}
}
}
现在显然,您应该检查进程的返回结果,并且可能会产生更好的与进程交互的机制,但这就是基本思想......
直接调用第二个类的main方法即可。 main 方法就像任何其他静态方法一样。
这对我有用:
try {
single.main(new String[0]);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
只需调用主类文件即可。例如,如果您的java类文件名是
xyz.java
,您可以通过单击JButton
在java swing应用程序中调用并执行相同的文件,代码是
private void Btn_createdatabaseActionPerformed(java.awt.event.ActionEvent evt) {
xyz.main(new String[0]);
}
就是这样...
您可以尝试组合使用两个开源库:jaxec和jhome(我是它们的作者)。这是从 Java 程序调用 Java 程序的方式:
import com.yegor256.Jaxec;
import com.yegor256.Jhome;
new Jaxec()
.with(new Jhome().path("bin/javac").toString())
.with("Hello.java")
.exec();
new Jaxec()
.with(new Jhome().path("bin/java").toString())
.with("Hello") // class name
.exec();
bin/java
和bin/javac
的绝对路径由Jhome
计算。