3

How to redirect or get the system output to String?

ProcessBuilder pb = new ProcessBuilder().inheritIO();
...

for (...){
    pb.command(...);
    pb.start();

    //here >>> assign output string to variable
}
4
  • Have you tried pb.redirectOutput(ProcessBuilder.Redirect.appendTo(myFile));? Commented Jul 1, 2015 at 8:09
  • 1
    possible duplicate of How to redirect Process Builder's output to a string? Commented Jul 1, 2015 at 8:10
  • 1
    i want to assign to a variable for processing, not to file. Commented Jul 1, 2015 at 8:11
  • ambiguous question. define "output". There are two common output channels, and any limits on the number of output channels are system dependent. We can assume you mean the standard output, and you might actually mean that, but then all of your answers will be opinions of the fact. I would be interested in seeing a THREE-WAY-STDIO (in, out and error channels) example. That would cover every channel, direction, and the required synchronization mechanism for BASIC I/O. Amazing how something so simple and pertinent could be so troublesome to locate. Commented Nov 3, 2017 at 6:24

2 Answers 2

1

Here is an opinion on how to capture the standard output of a system command process into a string container.

Adapted from the web:

try {
  ProcessBuilder pb = new ProcessBuilder("echo", "dummy io");
  final Process p=pb.start();
  BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
  String line;
  StringBuilder sb = new StringBuilder();
  while((line=br.readLine())!=null) sb.append(line);
}

System.out.println(sb.toString());
Sign up to request clarification or add additional context in comments.

1 Comment

It may be a good idea to add p.waitFor() before collecting the string together. Also you can replace line and sb by using br.lines().collect(Collectors.joining("\n"))
0

In congruence with my original comment on what would be a good example of Basic I/O. I hacked out some code, with a few more features than basic.


Extras

  • An environment shell for variables and
  • A working directory

These features add "profile-style" execution to your System commands.


Foundational Work

Java Threading and Joining by Oracle.


Code

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by triston on 11/2/17.
 */

public class Commander {

  private Commander(){} // no construction

  public static class StreamHandler implements Runnable {

    Object source;
    Object destination;

    StreamHandler(Object source, Object oDestination) {
      this.source = source; this.destination = oDestination;
    }

    public void run() {
      if (source instanceof InputStream) {
        BufferedReader br = new BufferedReader(new InputStreamReader((InputStream) source));
        String line;
        try {
          while ((line = br.readLine()) != null) ((StringBuilder) destination).append(line + '\n');
        } catch (IOException oE) {
        }
      } else {
        PrintWriter pw = new PrintWriter((OutputStream)destination);
        pw.print((String)source);
        pw.flush(); pw.close();
      }
    }

    public static Thread read(InputStream source, StringBuilder dest) {
      Thread thread = new Thread(new StreamHandler(source, dest));
      (thread).start();
      return thread;
    }

    public static Thread write(String source, OutputStream dest) {
      Thread thread = new Thread(new StreamHandler(source, dest));
      (thread).start();
      return thread;
    }

  }

  static Map<String, String> environment = loadEnvironment();

  static String workingDirectory = ".";

  static Map<String, String> loadEnvironment() {
    ProcessBuilder x = new ProcessBuilder();
    return x.environment();
  }

  static public void resetEnvironment() {
    environment = loadEnvironment();
    workingDirectory = ".";
  }

  static public void loadEnvirons(HashMap input) {
    environment.putAll(input);
  }

  static public String getEnviron(String name) {
    return environment.get(name);
  }

  static public void setEnviron(String name, String value) {
    environment.put(name, value);
  }

  static public boolean clearEnviron(String name) {
    return environment.remove(name) != null;
  }

  static public boolean setWorkingDirectory(String path) {
    File test = new File(path);
    if (!test.isDirectory()) return false;
    workingDirectory = path;
    return true;
  }

  static public String getWorkingDirectory() {
    return workingDirectory;
  }

  static public class Command {

    ProcessBuilder processBuilder = new ProcessBuilder();
    Process process;

    public Command(String... parameters) {
      processBuilder.environment().putAll(environment);
      processBuilder.directory(new File(workingDirectory));
      processBuilder.command(parameters);
    }

    public int start(String input, StringBuilder output, StringBuilder error) throws IOException {

      // start the process
      process = processBuilder.start();

      // start the error reader
      Thread errorBranch = StreamHandler.read(process.getErrorStream(), error);

      // start the output reader
      Thread outputBranch = StreamHandler.read(process.getInputStream(), output);

      // start the input
      Thread inputBranch = StreamHandler.write(input, process.getOutputStream());

      int rValue = 254;
      try {
        inputBranch.join(); rValue--;
        outputBranch.join(); rValue--;
        errorBranch.join(); rValue--;
        return process.waitFor();
      } catch (InterruptedException oE) {
        oE.printStackTrace();
        return rValue;
      }

  }

}

Testing

@Test public void foo() {
  Command cmd = new Command("sh", "--");
  StringBuilder output = new StringBuilder();
  StringBuilder error = new StringBuilder();
  int pValue = 127;
  try {
    pValue = cmd.start("echo well done > /dev/stderr\n\necho oh, wow; false", output, error);
  } catch (IOException oE) {
  }
  System.out.println("output: "+output.toString());
  System.out.println("error: "+error.toString());
  System.out.println("\nExit code: "+pValue);
  System.exit(pValue);
}

Bring your own package and JUnit annotations. This sample code demonstrates return value, command input, command standard output, and command error output.

My original design, called for the main thread to perform the standard output processing.

Have a great day.

2 Comments

This code needs review. A fan of these threading theories I am not. I cannot comprehend why these software machine networks (threads), cannot collectively perform in aggregate harmony "out of the box". For example, an IRC server is actually a software machine managing the concurrent communications of multiple threads AND network endpoints. Perhaps, the threading technology is based on a poor methodology from long beyond yesteryear.
[synchronization=que with intermediate life-cycle states: ready, active, paused, and terminated with a set of signals to manage and communicate between nodes]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.