Execute Java class passing parameters to the Scanner

3

We are creating a Java programming championship and would like students to make an algorithm that reads from a scanner and computes a particular mathematical logic and returns it to the system output.

Until this point OK. The problem is that I'm trying to run an autocorretor for the algorithms with this I need to run the java class and get the return to know if the calculation is right.

The main problem is that students use the scanner, so I can not pass the parameters. With the Rumtime.getRuntime().exec("java MinhaClasse); class I can not power the Scanner, I tried to replace System.in by setting it to an inputStream with a text file I created, but it does not work because another instance of Java is being started the code does not execute. I tried to look for something related to Reflection but I have not found anything yet. If anyone has any tips I will be very grateful.

    
asked by anonymous 04.05.2016 / 05:16

1 answer

4

Writing in child process

The simplest way to resolve the problem is to retrieve the method return Runtime#exec() ", which is of type Process and then using the Process#getOutputStream to be able to write directly to the input of the process.

Example:

Process p = Runtime.getRuntime().exec("java MinhaClasse);
OutputStream stdin = process.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
writer.write("Valor 1\n");
writer.write("Valor 2\n");
writer.write("Valor 2\n");
writer.flush(); // pode chamar várias vezes, dependendo do volume
writer.close(); // opcional, somente quando acabar a entrada

The line break ( \n ) after the values serve to emulate the Enter key that the user presses when entering a value for Scanner .

Beware of buffers and deadlocks

Something very important is that whenever you write something to the child process you must call the flush() method of OutputStream .

This is because OutputStream may have some buffer that may not immediately get to the child process, leaving it locked indefinitely.

And such care is all the more important if the parent process reads the child's output, because in that case the two can be locked indefinitely.

ProcessBuilder

Another tip is that using ProcessBuilder gives you greater flexibility in building the child process.

This can make a difference if you need to pass more parameters or something more complex.

Alternative # 1 - using native resources

An alternative would still be to use the command line power of the operating system and make the pipe for the entry of the Java program from some text file. Example:

cat input.txt | java MinhaClasse

Alternative # 2 - using a file as input

Another alternative to competition is to not pass the data through programming in the main process. I believe this could influence the runtime of the program.

The idea would be to put the input file in a read-only directory on the disk and pass the path to this file as a parameter to the program.

Then, simply instruct participants to create the Scanner " based on a constructor that receives a file.

Example:

public static void main(String[] args) {
    Scanner input = new Scanner(new File(args[0));
    ...
}

Much simpler, with no implementation difficulty or execution risk.

    
04.05.2016 / 10:58