InheritIO 和重定向标准输出

InheritIO and redirecting stdout

我正在尝试为使用 ProcessBuilder.inheritIO 的 class 编写测试,但我似乎无法让它工作。我已经将代码剥离到核心并提出了以下示例,我认为应该将子进程的所有输出写入 ByteArrayOutputStream 但没有。

环境:Java9.0.4 Windows7

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 没有按我的想法行事,但我不确定。我发现其他 SO 问题建议使用 StreamGrabber,但我认为这是针对 Java 6 及更早版本的,并且 inheritIO 对我有用。任何帮助,将不胜感激。谢谢。

编辑 我开始意识到调用 System.setOut() 并不是我所希望的那样。它不会更改 1 的基础文件描述符。如果我在 C 中这样做,我将使用低级文件描述符。但这不是 setOut() 所做的。那只是改变指针。

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