如何将Process Builder的输出重定向到字符串?

Ank*_*and 56 java stream processbuilder

我正在使用以下代码来启动进程构建器.我想知道如何将其输出重定向到String.

ProcessBuilder pb = new ProcessBuilder(System.getProperty("user.dir")+"/src/generate_list.sh", filename);
Process p = pb.start();
Run Code Online (Sandbox Code Playgroud)

我试过使用,ByteArrayOutputStream但它似乎没有用.

Rei*_*eus 69

从中读取InputStream.您可以将输出附加到StringBuilder:

BufferedReader reader = 
                new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ( (line = reader.readLine()) != null) {
   builder.append(line);
   builder.append(System.getProperty("line.separator"));
}
String result = builder.toString();
Run Code Online (Sandbox Code Playgroud)

  • @Fabian这可以使用`processBuilder.inheritIO()`轻松完成 (6认同)
  • 您可能想要添加如何获取错误流,或两者. (3认同)
  • 请注意,如果不重定向错误流,则需要捕获错误流的输出以及输入流,否则该过程将挂起。您必须将流收集在单独的线程中,否则主线程将挂起。在这种情况下,请搜索“狼牙线”以获取完整的解决方案。 (2认同)

Dan*_*iel 21

使用Apache Commons IOUtils,您可以在一行中完成:

ProcessBuilder pb = new ProcessBuilder("pwd");
String output = IOUtils.toString(pb.start().getInputStream(), StandardCharsets.UTF_8);
Run Code Online (Sandbox Code Playgroud)


Gre*_*g T 10

Java 8示例:

public static String runCommandForOutput(List<String> params) {
    ProcessBuilder pb = new ProcessBuilder(params);
    Process p;
    String result = "";
    try {
        p = pb.start();
        final BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

        StringJoiner sj = new StringJoiner(System.getProperty("line.separator"));
        reader.lines().iterator().forEachRemaining(sj::add);
        result = sj.toString();

        p.waitFor();
        p.destroy();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

用法:

List<String> params = Arrays.asList("/bin/sh", "-c", "cat /proc/cpuinfo");
String result = runCommandForOutput(params);
Run Code Online (Sandbox Code Playgroud)

我使用这个确切的代码,它适用于单行或多行结果.您也可以添加错误流处理程序.


fGo*_*fGo 9

你可能会这样做:

private static BufferedReader getOutput(Process p) {
    return new BufferedReader(new InputStreamReader(p.getInputStream()));
}

private static BufferedReader getError(Process p) {
    return new BufferedReader(new InputStreamReader(p.getErrorStream()));
}
...
Process p = Runtime.getRuntime().exec(commande);
BufferedReader output = getOutput(p);
BufferedReader error = getError(p);
String ligne = "";

while ((ligne = output.readLine()) != null) {
    System.out.println(ligne);
}

while ((ligne = error.readLine()) != null) {
 System.out.println(ligne);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果进程将大量数据写入stderr,这可能会挂起 - 请参阅http://stackoverflow.com/questions/16983372/why-does-process-hang-if-the-parent-does-not-consume-stdout-标准错误,在Java的 (6认同)

kme*_*cpp 6

Java 9 开始,我们终于有了一个单行代码:

ProcessBuilder pb = new ProcessBuilder("pwd");
Process process = pb.start();

String result = new String(process.getInputStream().readAllBytes());
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案是错误的,因为你 a.) 需要读取 stdout 和 stdin 并且 b.) 在单独的线程上执行此操作。原因(正如上面 Richard Whitehead 已经解释的那样)是进程会将 stdout/stderr 输出写入固定大小的缓冲区,如果这些缓冲区已满并且永远不会被读取,则进程将无限期地阻塞。 (2认同)

tho*_*iha 5

只需添加.inheritIO();到流程构建器行。

IE:

ProcessBuilder pb = new ProcessBuilder(script.sh).inheritIO();

  • 这会将进程的 `stdOut` 和 `stdErr` 重定向到 Java 的标准输出和错误;它不允许您将输出捕获为字符串。 (4认同)
  • @DavidFernandez我认为你不能以这种方式使用`inheritIO`;我可能会使用上述解决方案之一使用输入流收集子进程的 stdout/stderr,并且每当我从这些流之一读取一些值时,我_也_只使用 `System.{out/stderr} .print` 将其复制到我的程序的输出中。(虽然对这个“简单”的事情有多困难感到沮丧。) (2认同)

Mic*_*ter 5

For Java 7 and 8 this should work:

private String getInputAsString(InputStream is)
{
   try(java.util.Scanner s = new java.util.Scanner(is)) 
   { 
       return s.useDelimiter("\\A").hasNext() ? s.next() : ""; 
   }
}
Run Code Online (Sandbox Code Playgroud)

Then in your code, do this:

String stdOut = getInputAsString(p.getInputStream());
String stdErr = getInputAsString(p.getErrorStream());
Run Code Online (Sandbox Code Playgroud)

I shamelessly stole that from: How to redirect Process Builder's output to a string?