Skip to content

Instantly share code, notes, and snippets.

@th-schwarz
Last active July 15, 2024 16:53
Show Gist options
  • Save th-schwarz/e9bb3deeed0b560b5cc390d3c5efb1ef to your computer and use it in GitHub Desktop.
Save th-schwarz/e9bb3deeed0b560b5cc390d3c5efb1ef to your computer and use it in GitHub Desktop.
A complete wrapper to the ProcessBuilder

There are many topics around the ProcessBuilder. The focus here is how to handle the output of executed commands correctly!

The following two things are important:

  • Consuming STDOUT and STDERR is necessary to avoid freezing!
  • If the process writes a large amount of output, it must be consumed. This can be done by calling ProcessBuilder#redirectErrorStream, which redirects STDERR to STDOUT!

I've written a wrapper object to the ProcessBuilder to handle and configure it easier. Have look at the code below.

Here is a simple example to demonstrate the usage:

public static void main(String[] args) throws Exception {
	ProcessBuilderWrapper pbw = new ProcessBuilderWrapper("ls", "-al");
	pbw.setWorkingDirectory("/tmp");
	pbw.redirectErrorStream();
	pbw.run();
	if(!pbw.hasErrors())
	  System.out.println(pbw.getOutput());
} 
/**
* GPL
*/
public class ProcessBuilderWrapper {
private String[] command;
private File workingDirectory;
// exit value of the process
private int status;
private boolean redirectToStdout;
private boolean redirectErrorStream;
private ByteArrayOutputStream outStd = new ByteArrayOutputStream();
private ByteArrayOutputStream outError = new ByteArrayOutputStream();
// environment variables, that are visible to the process
private Map<String, String> environment = null;
public ProcessBuilderWrapper(String... command) {
this.command = command;
}
public void run() throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder(command);
if(workingDirectory != null)
pb.directory(workingDirectory);
if(environment != null && environment.size() > 0)
pb.environment().putAll(environment);
pb.redirectErrorStream(redirectErrorStream);
Process process = pb.start();
try (var infoStream = process.getInputStream(); var errorStream = process.getErrorStream()) {
if(redirectToStdout) {
infoStream.transferTo(System.out);
errorStream.transferTo(System.out);
} else {
infoStream.transferTo(this.outStd);
errorStream.transferTo(this.outError);
}
}
status = process.waitFor();
}
public void redirectToStdOut() {
this.redirectToStdout = true;
}
public void redirectErrorStream() {
this.redirectErrorStream = true;
}
public void setWorkingDirectory(String dir) {
this.workingDirectory = Paths.get(dir).toFile();
}
public void setEnvironment(Map<String, String> environment) {
this.environment = environment;
}
public int getStatus() {
return status;
}
public String getOutput() {
return (redirectToStdout) ? "n/a" : outStd.toString();
}
public String getError() {
return (redirectToStdout) ? "n/a" : outError.toString();
}
public boolean hasErrors() {
return getStatus() != 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment