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);
Related
I have read this question:
Java Programming: call an exe from Java and passing parameters
And this answer is good enough
https://stackoverflow.com/a/5604756/2674303
But I additionally want to pass parameters to stdin of external process and read from stdout of this process.
How can I do this?
My efforts:
main method:
public class ProcessBuilderTest {
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("C:\\Program Files\\Java\\jdk1.8.0_111\\bin\\java",
"-cp", //class path key
"C:\\Users\\redwhite\\IdeaProjects\\HelloMyWorld\\out\\production\\HelloMyWorld" , // path to class file of ExternalProcess class
"call_external.ExternalProcess"); // fully qualified name
Process process = pb.start();
OutputStream processOutputStream = process.getOutputStream();
IOUtils.write("1" + System.lineSeparator(), processOutputStream);
InputStream processInputStream = process.getInputStream();
System.out.println("--1--");
System.out.println(process.isAlive()); // outputs true
String result = IOUtils.toString(processInputStream, "UTF-8"); //<-- hangs here
System.out.println("--2--");
process.waitFor();
System.out.println(result); // expect to see processed[1]
}
}
ExternalProcess await string from stdin and produce another string to stdout:
package call_external;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Created by redwhite on 27.03.2017.
*/
public class ExternalProcess {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine();
System.out.println("processed[" + input + "]");
}
}
This code hangs.I cannot understand why
I don't know what the IOUtils class is and what the toString() method is doing. However, a way to read from the InputStream is:
InputStreamReader isr;
BufferedReader br;
String input = "";
String line;
try {
isr = new InputStreamReader( p.getInputStream );
br = new BufferedReader( isr );
while( (line = br.readLine()) != null ) {
input += line + "\n";
}
} catch( Exception e ) {
e.printStackTrace();
}
If I well understood your problem, you are looking for a popen-equivalent function in Java. Maybe this discussion can help you :)
Java: popen()-like function?
Instead of adding \n in the end of line, stream should be closed
thus after replacing
IOUtils.write("1" + System.lineSeparator(), processOutputStream);
with
IOUtils.write("1", processOutputStream);
processOutputStream.close();
Code became work properly
I want to run a C code through Java to print an integer which is entered by the user. I'm using ProcessBuilder class.
The Java code gives the same output (stdout:0) for every integer that I input through outputstream.
public class test {
public static void main(String args[]) throws IOException {
String line;
ProcessBuilder builder = new ProcessBuilder("first1.exe");
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
InputStream err=process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
writer.write(8);
writer.flush();
line = reader.readLine();
System.out.println("Stdout: " + line);
}
}
I always get the output:
stdout:0
The C code for first1.exe is:
#include <stdio.h>
int main ()
{
int n;
scanf("%d",&n);
printf("%d",n);
return 0;
}
use
process.waitFor();
writer.write(8+"\n");
enter code here
In the above code when the C code first1.exe executes, it waits for an input to be given.
Here the writer just writes 8 and does nothing while the code first1.exe requires the user to write 8 and press enter.
The above code does not work because enter or newline is not given.
Replacing the line writer.write(8); with writer.write(8+"\n"); and add process.waitFor() before writer.write(8+"\n") and it will work properly.
On replacing the statement, the code gives stdout:8 as output.
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 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
The following code(when executed) prompts the user to enter any java class name to execute.
import java.io.*;
public class exec {
public static void main(String argv[]) {
try {
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
System.out.println("Enter the java class name");
String s=br.readLine();
Process pro=Runtime.getRuntime().exec(s);
BufferedReader in=new BufferedReader(new InputStreamReader(pro.getInputStream()));
String line=null;
while((line=in.readLine())!=null) {
System.out.println(line);
}
in.close();
} catch(Exception err) {
err.printStackTrace();
}
}
This code works fine if I'm using command prompt and I'm able to execute another java program. But I'm unable to do the same using eclipse.No output or error is showing up once I enter the java class name.
I'm new to eclipse. Need help.
You can't "execute" a java class, so your code as posted can't work.
Instead, you'll need to execute "java" and pass to it the classpath and class name as parameters, something like this:
String s = br.readLine();
String[] cmd = {"java", "-cp", "/some/path/to/your/jar/file", s};
Process pro = Runtime.getRuntime().exec(cmd);
Do you just enter the name of the class, or do you also enter the directory of where the program is located? I think it doesn't work in eclipse because you need to specify where the file is... like C:\Users\Me\workspace\ProjectName\src\filename