简体   繁体   English

将ProcessBuilder的输出管道输送到另一个ProcessBuilder

[英]piping output of ProcessBuilder to another ProcessBuilder

Is it possible to pass the output of one process created by ProcessBuilder to another process created by another ProcessBuilder? 是否可以将由ProcessBuilder创建的一个过程的输出传递给由另一个ProcessBuilder创建的另一个过程? For example, if I'm trying to execute this shell command: 例如,如果我尝试执行此shell命令:

ls | grep build.xml

how should I do it with ProcessBuilder? 我应该如何使用ProcessBuilder?

as @erdinc suggested, I tried this: 正如@erdinc所建议的,我尝试了此操作:

Process process = Runtime.getRuntime().exec("ls");
InputStream is = process.getInputStream();
byte[] buf = new byte[1000];
is.read(buf);
String parameter = new String(buf);
System.out.println("grep build " + parameter);

Process proc2 = Runtime.getRuntime().exec("grep build " + parameter);
InputStream is2 = proc2.getInputStream();
byte[] buf2 = new byte[1000];
is2.read(buf2);
String result = new String(buf2);
System.out.println("proc2 result: " + result);

but it produces different result compare to when I run the script directly in the shell. 但是与直接在外壳中运行脚本相比,它产生了不同的结果。 Where did I do wrong? 我在哪里做错了?

Solved: Please see Philipp Wendler solution 解决:请参阅Philipp Wendler解决方案

The problem with the solution you have is that it reads only the first 1000 bytes from the output of ls and passes them to grep. 您所拥有的解决方案的问题在于,它仅从ls的输出中读取前1000个字节,并将其传递给grep。 As you don't know the amount of output from ls before, you need to read it iteratively until it is exhausted. 由于您以前不知道ls的输出量,因此需要迭代读取它,直到用尽为止。

Here is a solution using BufferedReader, which will send each line of output to grep: 这是使用BufferedReader的解决方案,它将每行输出发送到grep:

Process lsProcess = Runtime.getRuntime().exec("ls");
BufferedReader lsOutput = new BufferedReader(new InputStreamReader(lsProcess.getInputStream()));
Process grepProcess = Runtime.getRuntime().exec("grep build.xml");
BufferedWriter grepInput = new BufferedWriter(new OutputStreamWriter(grepProcess.getOutputStream()));

String line;
// read each line from ls until there are no more
while ((line = lsOutput.readLine()) != null) {
    // and send them to grep
    grepInput.write(line);
    grepInput.newLine();
}

// send end-of-file signal to grep so it will terminate itself
grepInput.close();

Of course you need to add the appropriate error-handling here. 当然,您需要在此处添加适当的错误处理。 You can omit the Reader and Writer and pass byte[] arrays directly from the input to the output stream if this solution is too slow. 如果此解决方案太慢,则可以忽略Reader和Writer并将byte[]数组直接从输入传递到输出流。

However, a much better solution would be not to use ls and grep to look for a file in the filesystem, but to use the appropriate Java API. 但是,更好的解决方案不是使用ls和grep在文件系统中查找文件,而是使用适当的Java API。 For example if you create a File object for the directory you are interested in, you can use the various listFiles methods on it to list all files in this directory. 例如,如果您为感兴趣的目录创建一个File对象,则可以在其上使用各种listFiles方法列出该目录中的所有文件。 This method is much easier, portable, less error-prone and probably faster. 这种方法更容易,可移植,不易出错并且可能更快。

You can use getInputStream method than pass as parameter second Process. 您可以使用getInputStream方法,然后将第二个Process作为参数传递。 Example code; 示例代码;

        process = Runtime.getRuntime().exec("ls");
        InputStream is = process.getInputStream();
        byte[] buf = new byte[1000];
        is.read(buf);
        String parameter = new String(buf);
        System.out.println(parameter);
        Runtime.getRuntime().exec("grep build.xml " + parameter);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM