将ProcessBuilder的输出导入另一个ProcessBuilder

10

是否可以将由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个回答

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和Writer,并直接从输入将byte[]数组传递到输出流。
然而,更好的解决方案是不使用ls和grep在文件系统中查找文件,而是使用适当的Java API。例如,如果为您感兴趣的目录创建了一个File对象,则可以使用其上的各种listFiles方法列出该目录中的所有文件。这种方法更简单、便携、不易出错,而且可能更快。

你的解决方案有效!谢谢Philipp :D 我实际上将使用这段代码来调用几个外部应用程序,例如chasen和moses(机器翻译工具)。ls | grep示例只是为了简化问题,但感谢您的建议:D 我会标记问题已解决并点赞您的解决方案。 - ndriks

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

但是如何将“ls”输入流传递给“grep”进程呢?我似乎找不到Process中的setInputStream方法。同时,使用ProcessBuilder可以实现吗? - ndriks
我尝试了你的解决方案@erdinc,但是与直接在shell中运行命令产生了不同的结果。我已经编辑了问题以展示我所做的事情。 顺便说一下,我不是试图使用ls结果作为参数运行grep,而是试图将ls的结果传递给grep进程。 - ndriks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接