So, I want to run a jar using java, get the output, and store it to a string.
I can see via the console that jar runs without any issues and I can see the output via console. However, the console values are not getting stored and returns null on printing.
What am I doing wrong? Please help.
The jdk used is jdk 11.
The code I have written so far:
public static void runTest(String Id, String token) throws IOException, InterruptedException{
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "./lib/Myjar.jar", Id, token);
pb.redirectErrorStream(true);
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process proc = pb.start();
System.out.println("Job running");
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
String result = builder.toString();
proc.waitFor();
System.out.println("Job finished");
System.out.println("Output:\n" + result);
}
The BufferedReader is empty and therefore you can't read anything in the while-loop. At the end, the StringBuilder is an empty object and the result String has no value.
Here is an example how you can read the Output from one jar in another Java Program:
First program: myjava.jar
public static void main(String[] args) {
System.out.println("Hello World");
}
And then the Java Code which is reading the output from myjava.jar:
public static void main(String[] args) throws IOException, InterruptedException {
String token = "t";
String Id = "x";
runTest(Id, token);
}
public static void runTest(String Id, String token) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "./myjava.jar", Id, token);
pb.redirectErrorStream(true);
pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
Process proc = pb.start();
System.out.println("Job running");
StringBuilder builder = new StringBuilder();
try(InputStream in = proc.getInputStream();
Scanner scanner = new Scanner(in)) {
while(scanner.hasNext()) {
builder.append(scanner.next());
}
} catch (Exception e) {
e.printStackTrace();
}
String result = builder.toString();
proc.waitFor();
System.out.println("Job finished");
System.out.println("Output:\n" + result);
}
Related
A very simple code running in the debugging mode perfectly but not working after installation of exe, giving no response/result in return. even no errors to trace.
After building a .exe and installing on my PC its happening, very strange.
tried process builder but the same thing, anyway to check/trace it. maybe paths ?
StringBuilder b = new StringBuilder();
Process p = Runtime.getRuntime().exec("wmic diskdrive get signature");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
b.append(line);
}
Please note: CMD /c before commands also return an empty response in actual env.
An internal windows command with arguments, like "wmic diskdrive ..."
can be executed easily by wrapping it up inside a cmd window.
Here is the working code snippet for running the wmic command encapsulated in a cmd window:
import java.io.*;
public class Wmic {
public static void main(String[] args) {
StringBuilder b = new StringBuilder();
try {
// Initialize a process object to run
// wmic command and its parameters
// inside a cmd window
Process process = Runtime.getRuntime()
.exec("cmd /c C:\\Windows\\System32\\wbem\\WMIC.exe diskdrive get signature");
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
b.append(line);
}
} catch (Exception ex) {
b.append(ex.toString());
}
System.out.println("Output: \n" + b.toString());
}
}
Output:
>javac Wmic.java
>java Wmic
Output:
Signature
More information:
https://mkyong.com/java/how-to-execute-shell-command-from-java/
The ProcessBuilder constructor takes a list of strings. When using ProcessBuilder to run a command, I separate all the words in the command into separate strings.
I read the output of the process in a separate thread. And I always wait for the command, that I launched via ProcessBuilder, to terminate.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
public class PrcBldTs {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("wmic","diskdrive","get","signature");
try {
Process proc = pb.start();
StreamGobbler error = new StreamGobbler(proc.getErrorStream());
StreamGobbler output = new StreamGobbler(proc.getInputStream());
Thread stdout = new Thread(output);
Thread stderr = new Thread(error);
stdout.start();
stderr.start();
int result = proc.waitFor();
stdout.join();
stderr.join();
System.out.println("Exit status = " + result);
if (result != 0) {
System.out.println(error.getContents());
}
else {
System.out.println(output.getContents());
}
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
class StreamGobbler implements Runnable {
private BufferedReader reader;
private StringWriter sw;
public StreamGobbler(InputStream is) {
InputStreamReader isr = new InputStreamReader(is);
reader = new BufferedReader(isr);
sw = new StringWriter();
}
public String getContents() {
return sw.toString();
}
public void run() {
try {
String line = reader.readLine();
while (line != null) {
sw.append(line);
sw.append(System.lineSeparator());
line = reader.readLine();
}
}
catch (IOException xIo) {
throw new RuntimeException(xIo);
}
}
}
Running the above code gave me the following output.
Exit status = 0
Signature
1145609371
I got a code which is running and displaying output successfully if I am executing something like "dir" but not displaying the output if I am running "java -version" or other command from java. Please help:
public static void execJob(){
try{
ProcessBuilder pb = new ProcessBuilder("C:\\myPrograms\\jdk1.7.0_79\\bin\\java.exe", "-version");
pb.directory(new File("src"));
Process process = pb.start();
IOThreadHandler outputHandler = new IOThreadHandler(process.getInputStream());
outputHandler.start();
process.waitFor();
System.out.println(outputHandler.getOutput());
}catch(Exception e) {
System.out.println(e.toString());
}
}
private static class IOThreadHandler extends Thread {
private InputStream inputStream;
private StringBuilder output = new StringBuilder();
IOThreadHandler(InputStream inputStream) {
this.inputStream = inputStream;
}
public void run() {
Scanner br = null;
try {
br = new Scanner(new InputStreamReader(inputStream));
String line = null;
while (br.hasNextLine()) {
line = br.nextLine();
output.append(line + System.getProperty("line.separator"));
}
} finally {
br.close();
}
}
java -version writes to stderr, so you need pb.redirectErrorStream(true); to capture the output.
ProcessBuilder pb = new ProcessBuilder("C:\\myPrograms\\jdk1.7.0_79\\bin\\java.exe", "-version");
pb.redirectErrorStream(true);
...
private static class IOThreadHandler extends Thread {
private InputStream inputStream;
private StringBuilder output = new StringBuilder();
IOThreadHandler(InputStream inputStream) {
this.inputStream = inputStream;
}
public void run() {
try (Scanner br = new Scanner(new InputStreamReader(inputStream))) {
String line = null;
while (br.hasNextLine()) {
line = br.nextLine();
output.append(line).append(System.getProperty("line.separator"));
}
}
}
public String getOutput() {
return output.toString();
}
}
I was trying to get the logcat content into a JTextPane. I used following code hoping it will return the content as String but it freeze and also, doesn't produce an error.
Process exec = null;
try {
exec = Runtime.getRuntime().exec("adb logcat -d");
InputStream errorStream = exec.getErrorStream();
BufferedReader ebr = new BufferedReader(new InputStreamReader(errorStream));
String errorLine;
while ((errorLine = ebr.readLine()) != null) {
System.out.println("[ERROR] :- " + errorLine);
}
if (exec.waitFor() == 0) {
InputStream infoStream = exec.getInputStream();
InputStreamReader isr = new InputStreamReader(infoStream);
BufferedReader ibr = new BufferedReader(isr);
String infoLine;
while ((infoLine = ibr.readLine()) != null) {
System.out.println("[INFO] :- " + infoLine);
}
}
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
} finally {
if (exec != null) {
exec.destroy();
}
}
I referred to some tutorials but, they were not filling my problem. Is this wrong? Are there any other methods to get the logcat content as a String programmatically? Sorry if this is a dumb question.
The issue you're seeing is that you're trying to process command streams and wait for the executing process, all in the same thread. It's blocking because the process reading the streams is waiting on the process and you're losing the stream input.
What you'll want to do is implement the function that reads/processes the command output (input stream) in another thread and kick off that thread when you start the process.
Second, you'll probably want to use ProcessBuilder rather than Runtime.exec.
Something like this can be adapted to do what you want:
public class Test {
public static void main(String[] args) throws Exception {
String startDir = System.getProperty("user.dir"); // start in current dir (change if needed)
ProcessBuilder pb = new ProcessBuilder("adb","logcat","-d");
pb.directory(new File(startDir)); // start directory
pb.redirectErrorStream(true); // redirect the error stream to stdout
Process p = pb.start(); // start the process
// start a new thread to handle the stream input
new Thread(new ProcessTestRunnable(p)).start();
p.waitFor(); // wait if needed
}
// mimics stream gobbler, but allows user to process the result
static class ProcessTestRunnable implements Runnable {
Process p;
BufferedReader br;
ProcessTestRunnable(Process p) {
this.p = p;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(p.getInputStream());
br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null)
{
// do something with the output here...
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Hi have written code for starting the server.
The code is as given below.
package javacode;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String command = "command to be executed to run the server(Path)";
String output = obj.executeCommand(command);
System.out.println(output);
}
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
The server has started in background when i run the java code, but i am using the linux command to check weather the server has started.
I want to know what return value is stored in Process object when i run
Process pro=Runtime.getRuntime().exec(command)
You can use process.exitValue() to retrieve the return value of the command you have executed.
Please have also a look at the javadoc: http://docs.oracle.com/javase/8/docs/api/java/lang/Process.html#exitValue--
p = Runtime.getRuntime().exec(command);
p.waitFor();
System.out.println("Command '"+command+"' finished with return code "+p.exitValue());
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String className = "str.java";
String command = "javac " + className;
String output = obj.executeCommand(command);
System.out.println(output);// prints the output of the executed command
}
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
I am trying to compile a Java file (str.java) from another Java class(ExecuteShellComand.java). What I am trying to do is if "str.java" compiles successfully then I want to execute "java str" command, but if the compilation fails then proper stacktrace or errors should be printed. I am storing the stacktrace or the errors in output variable.
But when I execute this code although "str.java" has somes errors in it System.out.println(output) is not printing the errors.
If you want to capture the errors from a command then you shall capture error stream instead of Input stream
So replace
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
with
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
The Process class tries to mimetize OS process. It means, process keep different output stream for error and normal messages and one stream for input. In UNIX, should be:
wc < file > wc.count 2> wc.error
In Java...
abstract InputStream getErrorStream()
Gets the error stream of the subprocess.
abstract InputStream getInputStream()
Gets the input stream of the subprocess.
abstract OutputStream getOutputStream()
So, you should use getErrorStream() to get errors..
Refactoring your code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String className = "str.java";
String command = "javac " + className;
obj.executeCommand(command);
System.out.println(obj.output);
System.out.println(obj.errors);
}
private String errors;
private String output;
private void executeCommand(String command) {
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
errors = readStream(p.getErrorStream());
output = readStream(p.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
private String readStream(InputStream inputStream) throws IOException {
StringBuffer output = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
return output.toString();
}
}