Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将ProcessBuilder的输出管道化到另一个ProcessBuilder_Java_Runtime.exec - Fatal编程技术网

Java 将ProcessBuilder的输出管道化到另一个ProcessBuilder

Java 将ProcessBuilder的输出管道化到另一个ProcessBuilder,java,runtime.exec,Java,Runtime.exec,是否可以将ProcessBuilder创建的一个进程的输出传递给另一个ProcessBuilder创建的另一个进程?例如,如果我试图执行此shell命令: ls | grep build.xml 我应该如何使用ProcessBuilder 正如@erdinc所建议的,我尝试了以下方法: Process process = Runtime.getRuntime().exec("ls"); InputStream is = process.getInputStream(); byte[] buf

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

您可以使用getInputStream方法而不是pass作为第二个进程的参数。 示例代码

        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的输出读取前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();
当然,您需要在这里添加适当的错误处理。 如果此解决方案太慢,您可以省略读写器,并将
字节[]
数组直接从输入流传递到输出流


然而,更好的解决方案不是使用ls和grep在文件系统中查找文件,而是使用适当的javaapi。例如,如果您为感兴趣的目录创建一个
文件
对象,则可以使用其上的各种
列表文件
方法列出此目录中的所有文件。这种方法更简单、可移植、不易出错,而且可能更快。

但是如何将“ls”输入流传递给“grep”进程呢?我似乎在进程中找不到方法setInputStream。也可以用ProcessBuilder完成吗?我已经尝试过您的解决方案@erdinc,但是它产生的结果与直接在shell中运行命令不同。我对问题进行了编辑,以显示我所做的。仅供参考,我并没有尝试使用ls result作为参数运行grep,但我正在尝试将ls的结果通过管道传输到grep进程。您的解决方案有效!谢谢你,Philipp:D实际上我将使用这段代码调用一些外部应用程序,比如chasen和moses(机器翻译工具)。ls | grep示例只是为了简化问题,但感谢您的建议:D我将标记已解决的问题并对您的解决方案进行投票。