Execute JAR and read the console output using InputStream - Java - java

I have a myfile.jar file which I'm executing through another Java program using ProcessBuilder and trying to read the console output of the jar using InputStream as follows:
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "myfile.jar", "arg1");
Process p = pb.start();
InputStream in = p.getInputStream();
InputStreamReader ins = new InputStreamReader(in);
BufferedReader br = new BufferedReader(ins);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
p.destroy();
When I execute the above code, I'm not getting anything printed on the console. The myfile.jar was not developed by myself. But when I read through the code of myfile.jar it uses the Logger to print on the console using ConsoleHandler. I assume this may be the issue.
EDIT: When java -jar myfile.jar arg1 is executed standalone on the console, it prints the output on the console.
This is driving me nuts for past 3 days. The direction to solve this problem would help me to learn more.

When processing an external process, you should not only consume/monitor the stdout, but also the stderr.
You could use a second reader to read the stderr stream from the process, but generally it's easier to combine the streams using ProcessBuilder#redirectErrorStream, which redirect the stderr through the processes InputStream.
Sometimes a process will output to the stderr instead of the stdout.
Even if you're not using the output of these streams, it's always a good idea to read them as some processes can stall if the streams are not flushed.

Related

Java redirect input and output stream

To excecute SENNA in the terminal I use the command:
senna.exe < input.txt > result.txt
Now I want to realize this in a java program. This is my code so far
ProcessBuilder builder = new ProcessBuilder("senna.exe");
builder.redirectErrorStream(true);
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
BufferedReader reader = new BufferedReader (new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
writer.write("This is a test sentence");;
writer.flush();
String line;
while ((line = reader.readLine ()) != null) {
System.out.println ("Stdout: " + line);
}
To redirect the input, output and error stream I used the code from this thread. The problem is that I get the following error message:
FATAL ERROR: unable to open file hash/words.lst
Am I doing something wrong?
From the examples you've given it seems that you're adapting Linux code from this thread to run on Windows with senna.exe.
From the error you're getting it seems that you forgot to change Linux's forward slash (/) to Windows' backslash (\).
Try changing your filepath's forwardslash to backslash.
As far as I can see, you haven't set the directory path to ProcessBuilder object. This error seems to be because there is a folder called 'hash' in senna folder which can't be reached.
Please try this:
builder.directory(new File("/yourpathtosenna/senna/")); (I am on a linux machine)
Your error should most probably change, but I am not sure if you will get the output as I am also struggling with running senna interactively through Java on a Linux machine at the moment.
Good luck and do update if you are successful!

Using ProcessBuilder to find version of Java

I am trying to use Java to find out the versions of Java installed on a machine. I have:
List<String> commands = new ArrayList<String>();
commands.add("java.exe");
commands.add("-version");
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("C:\\Program Files\\Java\\jdk1.6.0_45\\bin"));
Process p = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
However, when this is run, the while loop is never executed as the stdInput is empty. If I take out the commands.add("-version"), it will get the input that is output when running "java.exe" command on command line, so it seems adding the -version arguement is causing issues and this also indicates that the directory and java.exe commands are correct. Any help would be appreciated.
The output of java -version is sent to the error stream - reading from that stream should result in the proper output:
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getErrorStream()));
Alternatively, you can call redirectErrorStream(true) to merge the Input and Error streams. If you just wish to just print to the command line, you can use inheritIO on the ProcessBuilder.
The currently running java version can be found without the need for a ProcessBuilder by retrieving the appropriate System property
System.out.println(System.getProperty("java.version"));
java -version prints to stderr. Try using:
ProcessBuilder pb = new ProcessBuilder(commands).redirectErrorStream(true);
That will put stderr in the same stream as stdout and the rest of your code can look as it does now.

Output from Process.getInputStream() buffered too long

I have a Java program that uses Process Builder to start an external program.
I have a Process Builder with the command, and I use the code below to get the program going.
What I want to do is to print out the output just as the external program would have done, and I try to do this with the following code:
pb.redirectErrorStream(true);
p = pb.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new inputStreamReader(is);
BufferedReader br = new BufferedReader(isr, 32);
while((line = br.readLine()) != null){
System.out.println(line);
}
The problem is that my program is all silent until the external program ends, when suddenly all output comes at once. Or it might not have benn silent if there had been more output, but I want it to produce the output as it comes, ie unbuffered.
The (to me) obvious problem is the BufferedReader and the size of its buffer, but the thing is that I've tried to have a really small buffer, to no avail.
I've also tried to avoid the BufferedReader, and work with the InputStreamReader directly instead, but thet bahaves the same way.
Anyone here that can understand my problem, and perhaps have a solution?
This is caused by buffering in the executed program, not by Java. Nothing you can do about it from the Java end.
This could help
Get Java Runtime Process running in background
run a thread when reading the output of an external application

Java: Redirecting inner process output when running from command line

I use the following code, for redirecting the output of a process I launch from my Java app:
ProcessBuilder builder = new ProcessBuilder("MyProcess.exe");
builder.redirectOutput(Redirect.INHERIT);
builder.redirectErrorStream(true);
Now, this works fine when I run the code from eclipse - I can see the output in Eclipse's console.
Yet when I create a jar file and run it from a cmd window, e.g. java -jar MyJar.jar, it doesn't print the output of the process. What could be the reason for this?
I know I'm late in answering, but I came across this question before coming across the answer, and wanted to save anybody else in the same boat some searching.
This is actually a known bug for Windows: https://bugs.openjdk.java.net/browse/JDK-8023130
You can get around it by redirecting the streams yourself:
Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
br.close();
It may be, that process is printing an error and exiting for some reason. So, the actual output goes into Err stream and not into the Out stream. Your code redirects Out stream only, so important process error information may be lost. I would suggest to inherit both Out and Err streams using this code:
ProcessBuilder builder = new ProcessBuilder("MyProcess.exe");
builder.inheritIO();
One more reason to redirect both streams is related to the output buffering for child process. If parent process (your java application) is not reading or redirecting standard streams (Out and Err) of the child process, then the latter may be blocked after a while, unable to make any further progress.
It definitely wouldn't hurt to have possible errors in the output anyway.

Running a batch file in Java on a remote server

I'm trying to use Java to interface with a large batch file that uses psexec to execute commands on remote servers.
I'm able to launch the file using process builder and it works fine for most commands, but seems to be getting hung up.
One particular command from the batch file is as follows:
ECHO .
Echo Which would you like to reboot?
Echo 1-10. For computers, enter computer number.
Echo E. Exit
set /p userinp=choose a number(0-22):
but from Java I get:
.
Which would you like to reboot?
1-10. For computers, enter computer number.
E. Exit
and then it hangs
It's clearly not reading the set line, but more importantly I haven't yet figured out how to pass input back to the subprocess.
String[] command = {"cmd", "/c", "batchfile", "restart"};
ProcessBuilder builder = new ProcessBuilder(command);
builder.directory(new File("C:\\"));
Process process = builder.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
Any input would be appreciated.
Your batch job requires that you actually provide input in order to proceed, which is why it appears to 'hang'. You need to supply this input to the process, via its output stream. A highly simplified example:
PrintWriter writer = new PrintWriter(process.getOutputStream());
writer.println("10");
writer.flush();
Your process doesn't hang, it is just waiting for some input at the command line, before to proceed.
As you are reading the output from the process via Process.getInputStream(), you can send input back to it using Process.getOutputStream().
public abstract OutputStream getOutputStream()
Gets the output stream of the subprocess. Output to the stream is piped into the standard input stream of the process represented by this Process object.
Implementation note: It is a good idea for the output stream to be buffered.
Returns:
the output stream connected to the normal input of the subprocess.

Categories

Resources