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

问题描述 投票:0回答:3

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

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

我希望

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

pb2.redirectInput(Redirect.PIPE);

但是,我如何指定我希望该管道从

pb1
的输出中读取?

java pipe processbuilder io-redirection
3个回答
9
投票

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:echo echo echo

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

输出过程2:echo


2
投票

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

startPipeline

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

0
投票

在java8中,您可以使用fifo创建管道ProcessBuilder

    static File createTempFifo() throws IOException, ErrnoException {
        File fifoFile = File.createTempFile("PipedProcessBuilders", ".fifo");
        fifoFile.delete();
        Os.mkfifo(fifoFile.getPath(), 0666);
        return fifoFile;
    }

    static Process[] startProcessBuildersPiped(ProcessBuilder... builders) throws IOException, ErrnoException {
        final Process[] processes = new Process[builders.length];
        ParcelFileDescriptor lastOutputPfd = null, lastInputPfd = null;
        for (int i = 0; i < builders.length; i++) {
            if (i < builders.length - 1) {
                builders[i].redirectOutput(Redirect.to(createTempFifo()));
                lastInputPfd = ParcelFileDescriptor.open(builders[i].redirectOutput().file(), ParcelFileDescriptor.MODE_READ_WRITE);
            }
            if (i > 0) {
                builders[i].redirectInput(Redirect.from(builders[i - 1].redirectOutput().file()));
            }
            processes[i] = builders[i].start();
            if (i > 0) {
                builders[i].redirectInput().file().delete();
                lastOutputPfd.close();
            }
            lastOutputPfd = lastInputPfd;
        }

        return processes;
    }
© www.soinside.com 2019 - 2024. All rights reserved.