我正在尝试为使用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()
正在做的事情。那只是在改变指针。
答案 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();