是否可以将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解决方案
答案 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);