I'm creating a program that will accept source codes, compile it, and input test cases to see whether the program was correct. A source code checker, if you may. What I used for compiling programs is through cmd. My problem now is how to enter the test cases once the programs are running in cmd.
This is actually a program for our school. So the professor will give a problem (ex. Input an integer, say if it's even or odd) then this program will check the students' source codes by testing the test cases provided by the professor (ex. input: 1 output: odd, input 2: output: even).
Here's my sample code (c# compiler)
case ".cs":
CsCompiler();
Run(path + "\\program");
break;
My functions:
public static void CsCompiler() throws IOException, InterruptedException {
Process(path + "\\", " c:\\Windows\\Microsoft.NET\\Framework\\v3.5\\csc /out:program.exe *.cs");
}
public static void Process(String command, String exe) throws IOException, InterruptedException {
final Process p;
if (command != null) {
p = Runtime.getRuntime().exec(exe, null, new File(command));
} else {
p = Runtime.getRuntime().exec(exe);
}
new Thread(new Runnable() {
public void run() {
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
try {
while ((line = input.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
p.waitFor();
}
public static void Run(String command) throws IOException, InterruptedException {
String[] argss = {"cmd", "/c", "start", command};
ProcessBuilder pb;
pb = new ProcessBuilder(argss);
pb.start();
}
If I got you right you want to start a program and fetch its output while injecting input from your java method. Actually thats very simple since you already did the ouput fetching in your compile method.
The Process Class also has a getOutputStream method that you can use for injecting input to your process.
I will show how to do this with an example.
Consider this simple C programm as a students source code that takes a number as input and checks if it is even or odd.
#include <stdio.h>
int main(){
int x;
printf("Enter an Integer Number:\n");
if (( scanf("%d", &x)) == 0){
printf("Error: not an Integer\n");
return 1;
}
if(x % 2 == 0) printf("even\n");
else printf("odd\n");
return 0;
}
Now implement your Run method like this to run the application, inject input, read output and check the return value.
public static void Run(String command, String input) throws IOException, InterruptedException {
// create process
String[] argss = {"cmd", "/c", command};
ProcessBuilder pb = new ProcessBuilder(argss);
Process process = pb.start();
// create write reader
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
// write input
writer.write(input + "\n");
writer.flush();
// read output
String line = "";
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// wait for process to finish
int returnValue = process.waitFor();
// close writer reader
reader.close();
writer.close();
System.out.println("Exit with value " + returnValue);
}
And thats it. If you invoke this method like this
Run("NumberChecker.exe", "1");
Run("NumberChecker.exe", "2");
Run("NumberChecker.exe", "a");
You will get the following output
Enter an Integer Number:
odd
Exit with value 0
Enter an Integer Number:
even
Exit with value 0
Enter an Integer Number:
Error: not an Integer
Exit with value 1
Related
I want to write a program which executes JARs and gets their output.
When the JAR program has only a print statement it works fine, but when it asks for input during execution, the program freezes.
Code of the JAR file program:
import java.util.*;
public class demo {
public static void main(String r[]) {
Scanner sc = new Scanner(System.in);
System.out.println("Hello ...");
System.out.println("please enter the number :");
int i = sc.nextInt();
System.out.println(" number : " + i);
}
}
Code of the original program which runs the JAR files:
public class jartorun {
public static void main(String arg[]) throws IOException {
String t = "javaw -jar D:\\jarcheck\\temp.jar";
Process p = Runtime.getRuntime().exec(t);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = input.readLine()) != null) {
System.out.print(line + "\n");
}
input.close();
}
}
I can give input to the JAR using process.getOutputStream(), but how would I use it so I can create a program which can give input to a JAR and read its output simultaneously?
If you want to run stuff outside the VM use the ProcessBuilder. Works fine for me and you can inherit the IO Stream.
ProcessBuilder builder = new ProcessBuilder("./script.sh",
"parameter1");
builder.directory(new File("/home/user/scripts/"));
builder.inheritIO();
try {
Process p = builder.start();
p.waitFor();
// Wait for to finish
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
This should also work with Windows batch scripts and paths.
(haven't tried the input though)
You can use p.getOutputStream() to provide input to the launched process.
I am trying to allow communication between one program (the program launcher, if you will) and the programs it launches via processbuilder. I have the output working fine, but the input seems to stop when it reaches the readline() method in helloworld (the created process).
Below is helloworld.java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class helloworld {
public static void main (String[] args) {
System.out.println ("println(\"Hello World!\")");
System.out.println ("getInput()");
Scanner in = new Scanner(System.in);
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String input = "";
try {
// wait until we have data to complete a readLine()
while (!br.ready()) {
Thread.sleep(200);
}
System.out.println("println(\"Attempting to resolve input\")");
input = br.readLine();
^This is where program hangs^
if(input != null){
System.out.println("println(\"This should appear\")");
}
System.out.println("println(\"input recieved " + input + "\")");
} catch (InterruptedException | IOException e) {
System.out.println("ConsoleInputReadTask() cancelled");
}
System.out.println("println(\"You said: " + input + "\")");
//System.out.println("println(\"You said: " + in. + "!\")");
in.close();
System.exit(0);
}
}
This is where the output (println) from the other process is recieved:
public void run() {
try {
//cfile = files[indexval].getAbsolutePath();
String[] commands =
{
"java", //Calling a java program
"-cp" , //Denoting class path
cfile.substring(0,cfile.lastIndexOf(File.separator) ), //File path
program}; //Class name
ProcessBuilder probuilder = new ProcessBuilder( commands );
//start the process
Process process = probuilder.start();
//Read out dir output
//probuilder.inheritIO(); //Can inherit all IO calls
InputStream is = process.getInputStream();
OutputStream os = process.getOutputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
BufferedReader br = new BufferedReader(isr);
String line;
/*System.out.printf("Output of running %s is:\n",
Arrays.toString(commands));*/
while ((line = br.readLine()) != null) {
myController.runCommand(line, "Please enter something!", bw);
//System.out.println(line);
}
br.close();
os.close();
} catch (IOException e){
e.printStackTrace();
}
System.out.println("programclosed");
}
And here is the function that it calls:
public synchronized void runCommand(String line, Object... arguments) throws IOException {
String[] tokens;
if(line.contains("(")){
tokens = line.split("\\(",2);
switch(tokens[0]){
case "println": //Println - format println(String strng)
tokens[1] = tokens[1].substring(1, tokens[1].length() - 2);
System.out.println(tokens[1]);
break;
case "getInput": //Get input - format getInput(String command, String message, BufferedWriter br)
Scanner reader = new Scanner(System.in);
System.out.println(arguments.length);
System.out.println(((String)arguments[0]));
BufferedWriter in = ((BufferedWriter)arguments[1]);
in.write(reader.nextLine());
System.out.println("sending input");
in.flush();
reader.close();
break;
default:
System.out.println("Invalid command recieved!");
}
} else
System.out.println("Invalid command recieved!");
}
The output I recieve is:
Hello World!
2
Please enter something!
This is a test input
sending input
Attempting to resolve input
As you can see, I successfully exit the while(!br.ready()) loop, and I stop at br.readLine();
I am aware inheritIO() exist, but for this case I am using the BufferedOuput to send commands which are then parsed and sent to the switch statement, which in turn calls the corresponding function. This is because multiple processes could be launched from the process manager, think of the fun when multiple System.in calls arrive, with nothing to determine which process it is for! In addition, this allows for me to call any type of function, even those not related to println or input.
I believe the issue here is a result of the following:
BufferedReader.ready() returns true if there are any characters available to be read. It does not guarantee that there are any carriage returns among them. (docs)
BufferedReader.readLine() looks for a carriage return to complete a line. If one is not found, it blocks.
BufferedWriter.write() does not automatically write a terminating carriage return.
To test whether this is actually the problem, replace this line in runCommand():
in.write(reader.nextLine());
with:
in.write(reader.nextLine() + "\n");
I have a problem when using while-loops to read the text a command returns.
I have the following code:
class CommandExecuter {
ProcessBuilder builder = null;
Process p = null;
BufferedWriter writer = null;
String str = "";
BufferedReader hey = null;
StringBuffer buffer = null;
CommandExecuter() {
}
public void run() {
builder = new ProcessBuilder("/bin/bash");
try {
p = builder.start();
}
catch (IOException e) {
e.printStackTrace();
}
writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
hey = new BufferedReader(new InputStreamReader(p.getInputStream()));
buffer = new StringBuffer();
}
String exec(String command) {
try {
writer.write(command);
writer.newLine();
writer.flush();
int a = 0;
while ((str = hey.readLine()) != null) {
a++;
System.out.println(a);
buffer = buffer.append(str + ":");
}
System.out.println("finished");
return buffer.toString();
}
catch (Exception e) {
e.printStackTrace();
}
return "1";
}
}
The problem is, the while loop is doesn't when the console finished printing text. It never reaches the part where it prints "finished". When using the command ls, it return a 8 lines long String. The variable "a" prints till it reaches 8, and stops, but the loop does not exit because it never reaches the finished part.
You are running an interactive shell and feeding it commands through standard input; once a command is executed, the shell will print its output and keep running, waiting for more commands. Therefore, standard output of the shell process will never be closed.
What you should probably do instead is run each command as its own, new, process, possibly as /bin/bash -c command.
I have C code that takes input from the console as,
main() {
int value;
printf("Enter a value");
scanf("%d", &value);
printf("the value is, %d", value);
return;
}
now I compile and create an .exe file. (say test.exe)
After that I want to call that executable file from a java code.
so, I used
public class JavaTest {
static String s=null;
public static void main(String[] args) throws java.io.IOException, java.lang.InterruptedException {
java.lang.Runtime rt = java.lang.Runtime.getRuntime();
System.out.println("start");
java.lang.Process p = rt.exec("test.exe");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
p.waitFor();
System.out.println("done.");
}
}
Obviously, that doesn't work. My question is, how do I pass the integer to the process during runtime? I don't want to pass it as command line parameter.
use the outputStream before you use the inputStream of the Process. Write the integer to the output.Stream
I'm using Runtime.getRuntime().exec in eclipse to run another java program from the current program.
I've used the following code.
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
System.out.println("Enter the class name");
String s=br.readLine();
String str="XYZ";
String[] cmd = {"java","-cp", "C:/Users/..../workspace/Testing/bin",s,str};
Process pro=Runtime.getRuntime().exec(cmd);
I'm also passing a string "XYZ" to that program. That program just accepts the string and displays
Your string is XYZ
But by using the line
String[] cmd = {"java","-cp",
"C:/Users/..../workspace/Testing/bin",s,str};
i'm able to run the program but it is not accepting any arguments. It is neither displaying the output nor showing any errors.
Where am i going wrong?
Consider the program to be called is
import java.io.*;
public class Test
{
public static void main(String[] args) throws IOException
{
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
System.out.println("Enter any string");
String s=br.readLine();
System.out.println("Your string is "+s);
}
}
This program should accept the string XYZ and prints Your string is XYZ
You need to read the output (and error) streams from the Process using getInputStream() and getErrorStream(). You’ll need a separate thread for this if you want to wait for the process to complete.
String[] cmd = {"java", "-cp", "C:/Users/..../workspace/Testing/bin", s, str};
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
final InputStream pOut = p.getInputStream();
Thread outputDrainer = new Thread()
{
public void run()
{
try
{
int c;
do
{
c = pOut.read();
if (c >= 0)
System.out.print((char)c);
}
while (c >= 0);
}
catch (IOException e)
{
e.printStackTrace();
}
}
};
outputDrainer.start();
p.waitFor();
If you are using Java 7 and want all output of the process to be redirected to the console, the code is considerably simpler:
String[] cmd = {"java", "-cp", "C:/Users/..../workspace/Testing/bin", s, str};
Process p = new ProcessBuilder(cmd).redirectError(Redirect.INHERIT)
.redirectOutput(Redirect.INHERIT)
.start();
p.waitFor();
The redirectError() and redirectOutput() methods with Redirect.INHERIT cause output to just be sent to the parent Java process.
You are executing javac, the language compiler. I believe you want to invoke the java runtime on the class file with your main method. Replace javac with java, and specify your main class.
You are passing your data as an Argument but reading it from System.in. If you read the data from the arguments it'll work. So do what #prunge said to capture what the subprocess print and use this as your test and everything will work just fine.
import java.io.*;
public class Test
{
public static void main(String[] args) throws IOException
{
if(args.length==0)
System.out.println("No String received");
else
System.out.println("Your string is " + args[0]);
}
}
Be sure that you check both the InputStream and the ErrorStream.
If you however want to pass the data via System.in then you have to change your call code to:
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
System.out.println("Enter the class name");
String s=br.readLine();
String str="XYZ";
String[] cmd = {"java","-cp", "C:/Users/..../workspace/Testing/bin",s};
Process pro=Runtime.getRuntime().exec(cmd);
PrintWriter output= new PrintWriter(pro.getOutputStream());
output.println(str);