2012-01-05 116 views
9

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

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中运行的脚本。我在哪里做错了?

解决:请参考菲利普·温德勒溶液

回答

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

当然,你需要添加相应的错误处理在这里。 如果此解决方案太慢,可以省略读取器和写入器,并将byte[]数组直接从输入流传递到输出流。

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

+0

您的解决方案可行!谢谢菲利普:我实际上会使用这个代码来调用几个外部应用程序,如chasen和moses(机器翻译工具)。 ls | grep的例子只是为了简化问题,但感谢您的建议:D我会标记问题解决并upvote您的解决方案。 – ndriks 2012-01-08 12:00:58

0

可以使用getInputStream方法比通过作为参数第二处理。 示例代码;

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

但如何将“ls”输入流传递给“grep”进程?我似乎无法在Process中找到方法setInputStream。也可以用ProcessBuilder完成吗? – ndriks 2012-01-05 22:29:04

+0

我试过你的解决方案@erdinc,但它产生了不同的结果,而不是直接在shell中运行命令。我编辑了这个问题来展示我所做的。 仅供参考,我没有试图用ls结果作为参数运行grep,但我试图将ls的结果传递给grep进程。 – ndriks 2012-01-08 09:02:28