使用Java中的ProcessBuilder将进程的输出重定向到另一个进程的输入

时间:2016-02-29 18:32:39

标签: java pipe processbuilder io-redirection

我有两个由processBuilders定义的进程:

ProcessBuilder pb1 = new ProcessBuilder (...)
ProcessBuilder pb2 = new ProcessBuilder (...)

我希望pb1的输出成为pb2的输入。 我在文档中发现我可以使用管道从另一个进程读取pb2的输入:

pb2.redirectInput(Redirect.PIPE);

但是,如何指定我希望此管道从pb1的输出中读取?

2 个答案:

答案 0 :(得分:3)

  

static ProcessBuilder.Redirect INHERIT表示子进程I / O.   源或目的地将与当前的相同   过程

     

static ProcessBuilder.Redirect PIPE表示子进程I / O.   将通过管道连接到当前的Java进程。

所以我不认为其中一个可以帮助您将一个进程的输出重定向到 另一个过程的输入。

所以,让我们的手弄脏并写一些代码。 相关的行是

RedirectStreams redirectStreams = new RedirectStreams(process1,process2);

其中带有重定向的线程用于进程I / O的启动。 其余的测试方法仅用于演示。 对于进程,我启动bash并通过echo命令输出。 因此,对于此特定示例,我嵌套了echo命令。

  

echo Foo

     
    

  
     

回声回声

     
    

回波

  
public class ProcessPipeTest {
@Test public void testPipe(){
    try {

        Process process1 = new ProcessBuilder("/bin/bash").start();
        Process process2 = new ProcessBuilder("/bin/bash").start();

        RedirectStreams redirectStreams = new RedirectStreams(process1,process2);


        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(process1.getOutputStream()));
        String command = "echo echo echo";
        System.out.println("Input process1: " + command);
        bufferedWriter.write(command + '\n');
        bufferedWriter.close();


        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process2.getInputStream()));
        String actualOutput = bufferedReader.readLine();
        System.out.println("Output process2: " + actualOutput);
        assertEquals("echo",actualOutput);

    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

在RedirectStreams类中,这个可以设计得更好 如果它运行安全,我还没有经过测试,但是它可以完成这项工作。

public class RedirectStreams {
public RedirectStreams(Process process1, Process process2) {
    final Process tmpProcess1 = process1;
    final Process tmpProcess2 = process2;
    new Thread(new Runnable() {
        @Override
        public void run() {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(tmpProcess1.getInputStream()));
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(tmpProcess2.getOutputStream()));
            String lineToPipe;

            try {

                while ((lineToPipe = bufferedReader.readLine()) != null){
                    System.out.println("Output process1 / Input process2:" + lineToPipe);
                    bufferedWriter.write(lineToPipe + '\n');
                    bufferedWriter.flush();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();
}
}
  

输入过程1:回声回声回声

     

输出过程1 /输入过程2:回声回声

     

输出过程2:echo

答案 1 :(得分:1)

从 JDK 9 开始,您可以像这样使用 startPipeline

ProcessBuilder.startPipeline(
    Arrays.asList(
        new ProcessBuilder(...),
        new ProcessBuilder(...),
        ...
    )
)