TWOF
TWOF

Reputation: 388

Compiling and executing using exec in Java fails using command that works from the command line

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

Upvotes: 0

Views: 81

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347184

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...

Upvotes: 1

Related Questions