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
Related
In Java, I am launching a child process like so:
String[] command = {"java", "-jar", jarPath};
Process childProcess = new ProcessBuilder().inheritIO().command(command).start();
I expect the child process to print Success! to standard output at some point (if things are successful). How do I periodically (e.g., every 5 seconds) check if there's a Success! line in the output that is created by the child process?
If you want to perform IO with the subprocess, don’t use inheritIO. Instead, capture the process’ output stream via getInputStream() and read it via a BufferedReader:
final Process childProcess = new ProcessBuilder().command(command).start();
try (final BufferedReader br = new BufferedReader(new InputStreamReader(childProcess.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) {
if (line.equals("Success!")) {
System.out.println("Successfully completed");
// Maybe, depending on whether you need the remaining output:
break;
} else {
// Handle output from process; e.g.:
System.out.println("No success yet.");
}
}
}
// At this point, the child process has not yet necessarily completed!
childProcess.waitFor();
Importantly, you don’t need to check for output periodically: the loop performs synchronous IO, that is, it will automatically wait until there’s output available from the child process. All you need to do is check whether the output is what you expect.
So... this is rather a loaded question, although that might not be obvious from just asking it.
I was not able to do this using the ProcessBuilder class
(maybe someone with more experience can answer using that route).
Here is what you need to do: use the class Runtime.getRuntime().exec(command) to run your command. This gives you easy access to the standard input and standard error streams.
Below is a general complete class you can use.
Usage:
final String jarPath = "jarPath.jar";
final String[] command = { "java.exe", "-jar", jarPath };
final CrossPlatformCommand childProcess = new CrossPlatformCommand();
final int exitCode = childProcess.execute(command[0] + " " + command[1] + " " + command[2]);
System.out.println("Parse child process output: " + childProcess.getInput());
Output:
Parse child process output: Success!
There are a few caveats with this: the dollar sign needs to be escaped in Linux. There may be other characters that need to be escaped (this has not been investigated fully, and you may need to modify this class if you are using other characters that need to be escaped.)
public class CrossPlatformCommand
{
private static final String SHELL_LINUX = "/bin/bash";
private static final int BUFFER_SIZE = 4096;
private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.getDefault());
private final StringBuffer error = new StringBuffer();
private final StringBuffer input = new StringBuffer();
public int execute(final String command) throws Exception
{
final int exitCode;
if (OS_NAME.startsWith("windows"))
{
exitCode = executeWindows(command);
}
else
{
exitCode = executeLinux(command); // OS_NAME.startsWith("linux")
}
return exitCode;
}
public String getError()
{
return this.error.toString();
}
public String getInput()
{
return this.input.toString();
}
private int executeLinux(final String command) throws Exception
{
final Process proc = Runtime.getRuntime().exec(SHELL_LINUX);
processLinuxCommand(proc, command);
return processStreams(proc);
}
private int executeWindows(final String command) throws Exception
{
final Process proc = Runtime.getRuntime().exec(command);
return processStreams(proc);
}
private static void processLinuxCommand(final Process proc, final String command) throws Exception
{
try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())))
{
// Dollar signs are special in Linux.
out.write(command.replace("$", "\\$"));
out.newLine();
out.flush();
}
}
private int processStreams(final Process proc) throws Exception
{
fillBuffer(proc.getInputStream(), this.input);
fillBuffer(proc.getErrorStream(), this.error);
return proc.waitFor();
}
private static void fillBuffer(final InputStream in, final StringBuffer sb) throws IOException
{
sb.setLength(0);
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
final char[] buffer = new char[BUFFER_SIZE];
final int length = reader.read(buffer);
for (int i = 0; i < length; i++)
{
sb.append(buffer[i]);
}
}
}
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'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
I am searching files based on extension. Now for each file found, want to run a command:
Lets assume file found: C:\Home\1\1.txt. My exe exists in: C:\Home\Hello.exe
I would like to run command something like: "C:\Home\Hello.exe C:\Home\1\1.txt"
similarly for C:\Home\ABC\2.txt - "C:\Home\Hello.exe C:\Home\ABC\2.txt"
Kindly help me how to pass a searched file as an input to execute a command.
Thanks,
Kino
You can use below program as a base and then customize further as per your rqeuirement
public class ProcessBuildDemo {
public static void main(String [] args) throws IOException {
String[] command = {"CMD", "/C", "dir"}; //In place of "dir" you can append the list of file paths that you have
ProcessBuilder probuilder = new ProcessBuilder( command );
//You can set up your work directory
probuilder.directory(new File("c:\\xyzwsdemo")); //This is the folder from where the command will be executed.
Process process = probuilder.start();
//Read out dir output
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
System.out.printf("Output of running %s is:\n",
Arrays.toString(command));
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//Wait to get exit value
try {
int exitValue = process.waitFor();
System.out.println("\n\nExit Value is " + exitValue);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Lets get you started:
Filter files using: FilenameFilter:
http://docs.oracle.com/javase/7/docs/api/java/io/FilenameFilter.html
Sample:
http://www.java-samples.com/showtutorial.php?tutorialid=384
And after you have got the files:
Use ProcessBuilder to execute:
http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
Sample:
http://www.xyzws.com/Javafaq/how-to-run-external-programs-by-using-java-processbuilder-class/189
If you are running your app from the command line (e.g. windows cmd), and your program name is Hello.java, only thing you have to do is to put in the argument, just like you did in your example. So it looks something like:
java Hello C:\Home\1\1.txt
I did not use exe, since this is an example, and the question is tagged with "java" tag.
Your Hello.java MUST have a main method that looks like this:
public static void main(String ... args) {
}
The parameter args are the actual parameters you enter in the command line. So to get the file name, you would have to do this:
public static void main(String ... args) {
String fileName= args[0];
}
And that's it. Later on, you can do with that whatever you want, i.e. open and edit a file:
File file= new File(fileName);
//do whatever with that file.
This code will help you
public static void main(String args[]) {
String filename;
try {
Runtime rt = Runtime.getRuntime();
filename = "";//read the file na,e
Process pr = rt.exec("C:\\Home\\Hello.exe " + filename );
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line=null;
while((line=input.readLine()) != null) {
System.out.println(line);
}
int exitVal = pr.waitFor();
System.out.println("Error "+exitVal);
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
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);