Because the Process will execute in a new thread it's likely that there is no output or incomplete output available when you come to your while loop.
Process p = pb.start();
// process runs in another thread parallel to this one
BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()));
// bri may be empty or incomplete.
while ((line = bri.readLine()) != null) {
RESULT+=line;
}
So you need to wait for the process to complete before attempting to interact with it's output. Try using the Process.waitFor() method to pause the current thread until your process has had an opportunity to complete.
Process p = pb.start();
p.waitFor(); // wait for process to finish then continue.
BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = bri.readLine()) != null) {
RESULT+=line;
}
This is only a simple approach you could also process the output of the process while it runs in parallel but then you would need to monitor the status of the process i.e. is it still running or has it completed, and the availability of output.
Answer from jsuhre on Stack OverflowBecause the Process will execute in a new thread it's likely that there is no output or incomplete output available when you come to your while loop.
Process p = pb.start();
// process runs in another thread parallel to this one
BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()));
// bri may be empty or incomplete.
while ((line = bri.readLine()) != null) {
RESULT+=line;
}
So you need to wait for the process to complete before attempting to interact with it's output. Try using the Process.waitFor() method to pause the current thread until your process has had an opportunity to complete.
Process p = pb.start();
p.waitFor(); // wait for process to finish then continue.
BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = bri.readLine()) != null) {
RESULT+=line;
}
This is only a simple approach you could also process the output of the process while it runs in parallel but then you would need to monitor the status of the process i.e. is it still running or has it completed, and the availability of output.
Use Apache Commons Exec, it will make your life much easier. Check the tutorials for information about basic usage. To read the command line output after obtaining an executor object (probably DefaultExecutor), create an OutputStream to whatever stream you wish (i.e a FileOutputStream instance may be, or System.out), and:
executor.setStreamHandler(new PumpStreamHandler(yourOutputStream));
Videos
You need to capture both the std out and std err in the process. You can then write std out to a file/mail or similar.
See this article for more info, and in particular note the StreamGobbler mechanism that captures stdout/err in separate threads. This is essential to prevent blocking and is the source of numerous errors if you don't do it properly!
Use ProcessBuilder. After calling start() you'll get a Process object from which you can get the stderr and stdout streams.
UPDATE: ProcessBuilder gives you more control; You don't have to use it but I find it easier in the long run. Especially the ability to redirect stderr to stdout which means you only have to suck down one stream.
Here's an example of what I think you want to do:
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
Process proc = pb.start();
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
int exit = -1;
while ((line = br.readLine()) != null) {
// Outputs your process execution
System.out.println(line);
try {
exit = proc.exitValue();
if (exit == 0) {
// Process finished
}
} catch (IllegalThreadStateException t) {
// The process has not yet finished.
// Should we stop it?
if (processMustStop())
// processMustStop can return true
// after time out, for example.
proc.destroy();
}
}
You can improve it :-) I don't have a real environment to test it now, but you can find some more information here.
I recommend checking out Apache Commons Exec to avoid recreating the wheel. It has some nice features like choosing between synchronous vs. asynchronous execution, as well as a standard solution to spawning a watchdog process that can help in timing out the execution in case it gets stuck.
I'm assuming you're invoking the other program through either ProcessBuilder or Runtime.exec() both return a Process object which has methods getInputStream() and getErrorStream() which allow you to listen on the output and error (stdout, stderr) streams of the other process.
Consider the following code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args){
Test t = new Test();
t.start();
}
private void start(){
String command = //Command to invoke the program
ProcessBuilder pb = new ProcessBuilder(command);
try{
Process p = pb.start();
InputStream stdout = p.getInputStream();
InputStream stderr = p.getErrorStream();
StreamListener stdoutReader = new StreamListener(stdout);
StreamListener stderrReader = new StreamListener(stderr);
Thread t_stdoutReader = new Thread(stdoutReader);
Thread t_stderrReader = new Thread(stderrReader);
t_stdoutReader.start();
t_stderrReader.start();
}catch(IOException n){
System.err.println("I/O Exception: " + n.getLocalizedMessage());
}
}
private class StreamListener implements Runnable{
private BufferedReader Reader;
private boolean Run;
public StreamListener(InputStream s){
Reader = new BufferedReader(new InputStreamReader(s));
Run = true;
}
public void run(){
String line;
try{
while(Run && (line = Reader.readLine()) != null){
//At this point, a line of the output from the external process has been grabbed. Process it however you want.
System.out.println("External Process: " + line);
}
}catch(IOException n){
System.err.println("StreamListener I/O Exception!");
}
}
}
}
grasp this example:
// Try these charsets for encoding text file
String[] csStrs = {"UTF-8", "UTF-16BE", "UTF-16LE", "UTF-16", "GB2312", "GBK", "BIG5"};
String outFileExt = "-out.txt"; // Output filenames are "charset-out.txt"
// Write text file in the specified file encoding charset
for (int i = 0; i < csStrs.length; ++i) {
try (OutputStreamWriter out =
new OutputStreamWriter(
new FileOutputStream(csStrs[i] + outFileExt), csStrs[i]);
BufferedWriter bufOut = new BufferedWriter(out)) { // Buffered for efficiency
System.out.println(out.getEncoding()); // Print file encoding charset
bufOut.write(message);
bufOut.flush();
} catch (IOException ex) {
ex.printStackTrace();
}
}
// Read raw bytes from various encoded files
// to check how the characters were encoded.
for (int i = 0; i < csStrs.length; ++i) {
try (BufferedInputStream in = new BufferedInputStream( // Buffered for efficiency
new FileInputStream(csStrs[i] + outFileExt))) {
System.out.printf("%10s", csStrs[i]); // Print file encoding charset
int inByte;
while ((inByte = in.read()) != -1) {
System.out.printf("%02X ", inByte); // Print Hex codes
}
System.out.println();
} catch (IOException ex) {
ex.printStackTrace();
}
}
// Read text file with character-stream specifying its encoding.
// The char will be translated from its file encoding charset to
// Java internal UCS-2.
for (int i = 0; i < csStrs.length; ++i) {
try (InputStreamReader in =
new InputStreamReader(
new FileInputStream(csStrs[i] + outFileExt), csStrs[i]);
BufferedReader bufIn = new BufferedReader(in)) { // Buffered for efficiency
System.out.println(in.getEncoding()); // print file encoding charset
int inChar;
int count = 0;
while ((inChar = in.read()) != -1) {
++count;
System.out.printf("[%d]'%c'(%04X) ", count, (char)inChar, inChar);
}
System.out.println();
} catch (IOException ex) {
ex.printStackTrace();
}
}
} }