This version is a Java 17 version using some built in convenience functions like the xyzReader
methods and the streaming API consumption of the output. Take note that the example works for programs not running long and returning immediately when ready, so no daemons (otherwise the output processing should be done in a thread while waiting for the process to exit.).
If all the exception handling is ignored the code is really short:
Process process = new ProcessBuilder("program", "param1", "param2").start();
// check your program's used exit code in case or error
if (process.waitFor() != 0) {
throw new IOException("Program failed.");
}
String out;
try (BufferedReader reader = process.inputReader()) {
out = reader.lines().collect(Collectors.joining());
}
A more verbose version with proper error handling:
Process process;
try {
process = new ProcessBuilder("myprogram", "param1",
"param2").start();
int errorCode = process.waitFor();
// adjust the error code for your use case, different programs migth not use 0 as success
if (errorCode != 0) {
try (BufferedReader reader = process.errorReader(StandardCharsets.UTF_8)) {
throw new RuntimeException(String.format("Program execution failed (code %d): %s", errorCode,
reader.lines().collect(Collectors.joining())));
}
}
} catch (IOException e) {
throw new RuntimeException("Could not invoke program.", e);
} catch (InterruptedException e) {
throw new RuntimeException("Could not wait for process exit.", e);
}
String output;
try (BufferedReader reader = process.inputReader()) {
output = reader.lines().collect(Collectors.joining());
} catch (IOException e) {
throw new RuntimeException("Could not invoke external program.", e);
}
Also take into account that maybe not the inputReader
is used for all output, but also the errorReader
holds some information of the program output. It can also be that programs are using the inputReader
for the error messages instead of the errorReader