本文介绍了在Java中使用exec编译和执行失败,使用命令行的命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我们的想法是,在下面的代码中的这一行

  Runtime.getRuntime()。exec(cd / Users / fnord / Documents / workspace / LearningJava / src / PackA /; javac classA.java; cd ..; java PackA.classA); 

应该和这一行做同样的事情

  cd / Users / fnord / Documents / workspace / LearningJava / src / PackA /; javac classA.java; cd ..;当从终端运行第二行时,java PackA.classA 

那就是编译并运行java代码。我误解exec()是如何工作的?如果是这样,那么完成我想要完成的工作的最好方法是什么?

  package PackA; 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

$ b public class classA {
public static void main(String [] args)throws Exception {
ClassLoader loader = classA.class.getClassLoader();

//将文件路径设置为当前.java文件的路径
File file = new File(loader.getResource(classA.class.getPackage()。getName()+ /\"+classA.class.getSimpleName()+\".class\").toString().replaceAll(\"file:,).replaceAll(bin,src)。replaceAll(sA.class ,sA.java));

BufferedReader in = new BufferedReader(new FileReader(file)); //建立将被用来读取这个.java文件的读取器
StringBuffer string = new StringBuffer(); //将用来保存这个.java文件内容的stringBuffer
String stringRead = in.readLine(); //设置一个字符串到这个.java文件的第一行

while((stringRead)!= null){//只要我们还没有到达文件的末尾
string.append(stringRead); //追加行
string.append(System.getProperty(line.separator)); //转到下一行
stringRead = in.readLine(); //读下一行
}

整数intToFind = new Integer(0); //找到的整数

if(intToFind< = 10){//只要intToFind小于或等于10
//递增stringBuffer中的intToFind
StringBuffer newProgram = new StringBuffer(string.toString()。replaceFirst([()+ intToFind.toString(),(+ String.valueOf(++ intToFind)));
//建立将被用来写入文件的作者
BufferedWriter out = new BufferedWriter(new FileWriter(file));

out.write(newProgram.toString()); //把这个newProgram写到这个.java文件中,增加intToFind

in.close(); //关闭读写器
out.close();

//进入java文件目录,编译代码,向下移动一个目录,执行.class文件
Runtime.getRuntime().exe(cd / Users / fnord / Documents / workspace / LearningJava / src / PackA /; javac classA.java; cd ..; j ava PackA.classA);




$ div class =h2_lin>解决方案

cd 不是一个程序,它是一个shell命令。

您可以使用 ProcessBuilder 代替,它可以让你定义从哪个工作目录上下文执行命令



类似于



前面例子中的代码被更新,提供了指定工作目录的能力

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

int result = p.waitFor();

consumer.join();

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

返回结果;


public class InputStreamConsumer extends Thread {

private InputStream is;
private IOException exp;
私有StringBuilder输出;

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


@Override
public void run(){
int in = -1;
output = new StringBuilder(64); ((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;






$ b你可以使用类似于

  compile(PackA / classA.java,new File(/ Users / fnord / Documents / workspace / LearningJava / src )); 

现在,如果你真的很有勇气,你可以看看 >,它使用javax.tools.JavaCompiler类来编译一个Java文件...


So the idea is that this line in the code below

Runtime.getRuntime().exec("cd /Users/fnord/Documents/workspace/LearningJava/src/PackA/; javac classA.java; cd ..; java PackA.classA");

should do the same thing as this line

cd /Users/fnord/Documents/workspace/LearningJava/src/PackA/; javac classA.java; cd ..; java PackA.classA

when that second line is run from a terminal. That is to compile and run the java code. Am I misunderstanding how exec() works? If so, what would be the best way to go about accomplishing what it is I want to accomplish?

package PackA;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;


public class classA {
    public static void main(String[] args) throws Exception{
        ClassLoader loader = classA.class.getClassLoader();

        //Sets the file path to the path of the current .java file
        File file = new File(loader.getResource(classA.class.getPackage().getName()+"/"+classA.class.getSimpleName()+".class").toString().replaceAll("file:", "").replaceAll("bin", "src").replaceAll("sA.class", "sA.java"));

        BufferedReader in = new BufferedReader(new FileReader(file)); //establishes the reader that will be used to read this .java file
        StringBuffer string = new StringBuffer(); //the stringBuffer that will be used to hold the contents of this .java file
        String stringRead = in.readLine(); //sets a string to the first line of this .java file

        while((stringRead) != null){ //as long as we haven't reached the end of the file
            string.append(stringRead); //append the line
            string.append(System.getProperty("line.separator")); //go to the next line
            stringRead = in.readLine(); //read the next line
        }

        Integer intToFind = new Integer(0); //the integer being looked for

        if (intToFind<=10) { //as long as the intToFind is less than or equal to 10
            //increment the intToFind in the stringBuffer
            StringBuffer newProgram = new StringBuffer(string.toString().replaceFirst("[(]"+intToFind.toString(), "("+String.valueOf(++intToFind)));
            //establishes the writer that will be used to write to the file
            BufferedWriter out = new BufferedWriter(new FileWriter(file));

            out.write(newProgram.toString()); //write the newProgram to this .java file with the incremented intToFind

            in.close(); //close both the reader and writer
            out.close();

            //Go to the directory of the java file, compile the code, move down one directory, execute the .class file
            Runtime.getRuntime().exec("cd /Users/fnord/Documents/workspace/LearningJava/src/PackA/; javac classA.java; cd ..; java PackA.classA");
        }
    }
}
解决方案

cd is not a program, it's a shell command.

You could use ProcessBuilder instead, which would allow you to define the working directory context from which the command should be executed

Something like this for example

Abbriviated code from previous example, updated to provide the ability to specifiy the working directory

public int compile(String file, File workingDirectory) throws IOException, InterruptedException {
    ProcessBuilder pb = new ProcessBuilder("javac", file);
    pb.redirectError();
    pb.directory(new File(workingDirectory));
    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;
    }
}

Which you could call using something like...

compile("PackA/classA.java", new File("/Users/fnord/Documents/workspace/LearningJava/src"));

Now, if you're really courageous, you could take a look at How do you dynamically compile and load external java classes?, which uses javax.tools.JavaCompiler` class to compile a Java file...

这篇关于在Java中使用exec编译和执行失败,使用命令行的命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 21:19
查看更多