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
}
JR Galia
  • 17,229
  • 19
  • 92
  • 144
  • Have you tried `pb.redirectOutput(ProcessBuilder.Redirect.appendTo(myFile));`? – Johan Tidén Jul 01 '15 at 08:09
  • 1
    possible duplicate of [How to redirect Process Builder's output to a string?](http://stackoverflow.com/questions/16714127/how-to-redirect-process-builders-output-to-a-string) – Chop Jul 01 '15 at 08:10
  • 1
    i want to assign to a variable for processing, not to file. – JR Galia Jul 01 '15 at 08: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. – Hypersoft Systems Nov 03 '17 at 06:24

2 Answers2

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());
  • 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"))` – Joshua Goldberg Nov 03 '18 at 03:31
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.

  • 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. – Hypersoft Systems Nov 03 '17 at 11:16
  • [synchronization=que with intermediate life-cycle states: ready, active, paused, and terminated with a set of signals to manage and communicate between nodes] – Hypersoft Systems Nov 03 '17 at 11:21