我有两个由 processBuilders 定义的流程:
ProcessBuilder pb1 = new ProcessBuilder (...)
ProcessBuilder pb2 = new ProcessBuilder (...)
我希望
pb1
的输出作为 pb2
的输入。
我在文档中发现我可以使用管道从另一个进程读取 pb2
的输入:
pb2.redirectInput(Redirect.PIPE);
但是,我如何指定我希望该管道从
pb1
的输出中读取?
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
startPipeline
:
ProcessBuilder.startPipeline(
Arrays.asList(
new ProcessBuilder(...),
new ProcessBuilder(...),
...
)
)
在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;
}