将ProcessBuilder的输出输出到另一个ProcessBuilder

时间:2012-01-05 20:44:17

标签: java runtime.exec

是否可以将ProcessBuilder创建的一个进程的输出传递给另一个ProcessBuilder创建的另一个进程?例如,如果我尝试执行此shell命令:

ls | grep build.xml

我应该如何使用ProcessBuilder?

正如@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);

但与直接在shell中运行脚本相比,它会产生不同的结果。我哪里做错了?

解决:请参阅Philipp Wendler解决方案

2 个答案:

答案 0 :(得分:6)

你所拥有的解决方案的问题是它只读取ls输出的前1000个字节并将它们传递给grep。由于您之前不知道ls的输出量,您需要反复读取它,直到它耗尽。

这是一个使用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();

当然,您需要在此处添加适当的错误处理。 如果此解决方案太慢,您可以省略Reader and Writer并将byte[]数组直接从输入传递到输出流。

但是,更好的解决方案是不使用ls和grep来查找文件系统中的文件,而是使用适当的Java API。例如,如果为感兴趣的目录创建File对象,则可以使用其上的各种listFiles方法列出此目录中的所有文件。这种方法更容易,更便携,更不容易出错,而且可能更快。

答案 1 :(得分:0)

您可以使用getInputStream方法而不是作为参数传递第二个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(parameter);
        Runtime.getRuntime().exec("grep build.xml " + parameter);