InheritIO和重定向标准输出

时间:2018-11-21 13:48:27

标签: java io processbuilder

我正在尝试为使用ProcessBuilder.inheritIO的类编写测试,但似乎无法使其正常工作。我已经将代码剥离到了核心,并提出了以下示例,我认为应该将子进程的所有输出都写到ByteArrayOutputStream上,但不要这样做。

环境:Windows 7上的Java 9.0.4

import java.io.*;

public class ProcessTest {
  public static void main(String[] args) throws Throwable {
    PrintStream original = System.out;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PrintStream ps = new PrintStream(baos);
    System.setOut(ps);

    System.out.println("BEGIN");
    Process process = new ProcessBuilder().command("where", "where")
                                          .inheritIO().start();
    process.waitFor();

    System.out.println("END");
    String output = new String(baos.toByteArray());
    original.println("output = " + output);
  }
}

输出为:

C:\Windows\System32\where.exe
output = BEGIN
END

当我在调试器中查看时,输出流不包含where的路径。

我在想System.setOut不在做我在想的事,但是我不确定。我发现还有其他问题建议使用StreamGrabber,但我认为这适用于Java 6及更早版本,并且InheritedIO将对我有效。任何帮助,将不胜感激。谢谢。

修改 我已经意识到,呼叫System.setOut()并没有真正实现我希望的目标。它不会更改1的基础文件描述符。如果我在C中执行此操作,则将使用低级文件描述符。但这不是setOut()正在做的事情。那只是在改变指针。

1 个答案:

答案 0 :(得分:0)

System.setOut更改Java进程的标准输出。无法保证会影响子进程。

无论如何,仅仅为了捕获单个进程的输出而更改全局设置可能不是一个好主意,尤其是如果您希望代码在其他代码(库,应用程序等)中运行时。

解决方案:请勿尝试入侵System.out。从流程的标准输出InputStream中读取:

ProcessBuilder builder = new ProcessBuilder().command("where", "where").inheritIO();
builder.redirectOutput(ProcessBuilder.Redirect.PIPE);
Process process = builder.start();

String output;
try (InputStream processStdOut = process.getInputStream()) {
    output = new String(processStdOut.readAllBytes());
}

process.waitFor();