I would like to print live output of a process in java; but the output is (almost) only available when the process stops execution.
In other words, when I run the same process with the command line, I get more frequent feedback (output) than when I execute it with Java.
I tested the following code to print the output every 250ms:
private static String printStream(BufferedReader bufferedReader) {
try {
String line = bufferedReader.readLine();
if(line != null) {
System.out.println(line);
}
return line;
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
public static void sendProcessStreams(Process process, SendMessage sendMessage) {
String[] command = { "/bin/bash", "-c", "custom_process"};
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File("."));
Process process = processBuilder.start();
BufferedReader inputBufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()), 1);
BufferedReader errorBufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream()), 1);
System.out.println("Start reading process");
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
String inputLine = printStream(inputBufferedReader);
String errorLine = printStream(errorBufferedReader);
if(inputLine == null && errorLine == null && !process.isAlive()) {
timer.cancel();
}
}
}, 0, 250);
}
Yet it only prints two lines, and then waits for the process to end before printing everything else.
Is it possible to get more frequent feedback from an external process? If not, Why not?
Your code basically (as far as reading from the output) works correctly, the problem is surely for another reason, please build a minimal problem that is reproducible (eg. what is custom_process
, why you use Timer
when you can use the current thread, ...).
Anyway, here's an example reading in realtime the output:
final Process proc = new ProcessBuilder(
"/bin/bash", "-c",
"for i in `seq 1 10`; do echo $i; sleep $((i % 2)); done")
.start();
try(InputStreamReader isr = new InputStreamReader(proc.getInputStream())) {
int c;
while((c = isr.read()) >= 0) {
System.out.print((char) c);
System.out.flush();
}
}
With output:
1 (and wait one second)
2
3 (and wait one second)
4
5 (and wait one second)
6
7 (and wait one second)
8
9 (and wait one second)
10