Usually, people would create two extra-threads in order to read the standard output and error respectively. However, the following code would allow to handle a Process outputs without those threads (it is arguably a little bit more difficult to decode the characters if you are using something else than a single-byte encoding and if you can't buffer the output in memory).
Although the following code seems to work, it is different enough from the "standard" solution, that I'm wondering if anyone can find am issue with it.
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process = processBuilder.start();
InputStream outputStream = null, errorStream = null;
ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream();
try {
outputStream = process.getInputStream();
errorStream = process.getErrorStream();
byte[] tmp = new byte[1024];
while (true) {
int outputBytes = readAvailablOnce(outputStream, outputBuffer, tmp);
int errorBytes = readAvailablOnce(errorStream, errorBuffer, tmp);
if (outputBytes == 0 && errorBytes == 0) {
try {
process.exitValue();
break;
} catch (IllegalThreadStateException e) {
// keep on looping
}
}
}
readAvailableAll(outputStream, outputBuffer, tmp);
readAvailableAll(errorStream, errorBuffer, tmp);
} finally {
closeQuietly(outputStream);
closeQuietly(errorStream);
}
System.out.println(outputBuffer.toString("ASCII"));
System.err.println(errorBuffer.toString("ASCII"));
System.err.println("exit code: " + process.exitValue());
}
private static void closeQuietly(InputStream in) {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// ignored
}
}
}
private static int readAvailablOnce(
InputStream inputStream, OutputStream outputStream, byte[] buffer)
throws IOException {
int bytesRead = 0;
if (inputStream.available() > 0) {
bytesRead = inputStream.read(buffer);
outputStream.write(buffer, 0, bytesRead);
}
return bytesRead;
}
private static void readAvailableAll(
InputStream inputStream, OutputStream outputStream, byte[] buffer)
throws IOException {
if (inputStream.available() > 0) {
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) >= 0) {
outputStream.write(buffer, 0, bytesRead);
}
}
}