0

I want to start two programs (as in ProcessBuilder), so that the first program's output is the second program's input. I additionaly want:

  1. To avoid using shell (so that I can pass arguments with spaces with no escaping hassle);
  2. To avoid all data flowing into parent Java process and back (i.e. having separate thread just to copy from one process's InputStream to the other process's OutputStream).

How to attain this?

Related: Building a process pipe with ProcessBuilder in Java 7 , but it uses shell...

Community
  • 1
  • 1
Vi.
  • 37,014
  • 18
  • 93
  • 148
  • You will have to instantiate two `ProcessBuilder`s anyway, since `program1` and `program2` will be two separate processes – fge Feb 12 '14 at 14:52
  • How to interconnect their output/input streams to flow directly from program1 to program2, without going though java? – Vi. Feb 12 '14 at 14:53
  • But you will have to... The same way the shell creates an anonymous pipe, you will have to do that in Java. There is no other way around this. – fge Feb 12 '14 at 15:01
  • @fge, 1. How to create anonymous pipe in Java? 2. How to specify the created pipe to ProcessBuilder? (without JNI) – Vi. Feb 12 '14 at 15:03

1 Answers1

0

Late answer; but you can use a named pipe. Create one first via mkfifo. Then in your Java code:

ProcessBuilder pb1 = new ProcessBuilder("gunzip", "-c", "log.gz");
ProcessBuilder pb2 = new ProcessBuilder("grep", "error");

File pipe = new File(NAMED_PIPE_PATH); // NAMED_PIPE_PATH points to what you created via mkfifo

pb1.redirectOutput(ProcessBuilder.Redirect.to(pipe));
pb2.redirectInput(ProcessBuilder.Redirect.from(pipe));

ProcessStartThread pst1 = new ProcessStartThread(pb1);
ProcessStartThread pst2 = new ProcessStartThread(pb2);
pst1.start();
pst2.start();

Note that ProcessStartThread is a simple custom class that extends Thread and basically does nothing other than call start() on the passed ProcessBuilder instance. The reason this has to be done from a separate thread is that ProcessBuilder.start() will hang until the other end of the named pipe is connected (it needs to open input/output to start execution).

edit: here is the ProcessStartThread class also:

class ProcessStartThread extends Thread {
    private ProcessBuilder procBuilder;
    private Process proc;
    public ProcessStartThread(ProcessBuilder procBuilder) {
        this.procBuilder = procBuilder;
        this.proc = null;
    }
    public void run() {
        try { this.proc = this.procBuilder.start(); } 
        catch ( Exception e ) { e.printStackTrace(); }
    }
    public Process getProcess() {
        return this.proc;
    }
}
Arthur
  • 584
  • 6
  • 14