【问题标题】:Redirecting the output of a process into the input of another process using ProcessBuilder in Java使用Java中的ProcessBuilder将进程的输出重定向到另一个进程的输入
【发布时间】:2023-10-01 15:01:01
【问题描述】:

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

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

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

pb2.redirectInput(Redirect.PIPE);

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

【问题讨论】:

    标签: java pipe processbuilder io-redirection


    【解决方案1】:

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

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

    所以我认为其中之一不会帮助您将一个进程的输出重定向到 另一个进程的输入。你必须自己实现它。

    实施:

    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();
    }
    
    }
    

    这个肯定可以设计得更好 而且我还没有测试过它运行是否安全,但它确实可以完成这项工作。

    用法:

    RedirectStreams redirectStreams = new RedirectStreams(process1,process2);
    

    测试:

    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();
        }
    }
    }
    

    输出:

    输入过程1:回显回显

    输出进程1 / 输入进程2:echo echo

    输出过程2:回显

    【讨论】:

    • 好的,谢谢。我期待一个使用 ProcessBuilder 方法的更简单的解决方案,但显然它不存在。
    【解决方案2】:

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

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

    【讨论】:

      最近更新 更多