Java:切换到新的流程创建样式(从 Runtime.getRuntime() 到 ProcessBuilder)

Java: Switch to new process creation style (from Runtime.getRuntime() to ProcessBuilder)

String command = "cmd.exe /c \"dir -d\"";
File workingDir = new File("C:\");

boolean newProcessStyle = true;
if (newProcessStyle) {
    ProcessBuilder pb = new ProcessBuilder(command);
    //redirect std_err to std_out
    pb.redirectErrorStream(true)
            .directory(workingDir);
    p = pb.start();
} else {
    String[] env = {};
    p = Runtime.getRuntime().exec(command, env, workingDir);
}

旧样式可以正常工作,新样式不行:cmd.exe 未找到。 使用processBuilder需要手动设置PATH吗?

顺便说一句:我仍然想知道为什么进程的 standard_ouput (stdout) 是由 p.getInputStream() 而不是 p.getOutputStream() 获得的。为什么它以 return 类型而不是功能命名?!

编辑: 附加问题: 为了确保子进程不会阻塞在完整的标准输出缓冲区上,需要读取输出缓冲区:

InputStream stdout = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
String line;
while ((line = reader.readLine())!= null) {
    output += line + "\n";
}
p.waitFor();

我不明白的是:如果 reader.readLine() returns 为 null,则缓冲区为空。如果子进程在父进程退出 while 循环后写入 stdout 怎么办?这不会导致同样的潜在死锁问题吗?

ProcessBuilder一样,每个部分分别给出,可执行文件和args。

你应该使用:

new ProcessBuilder("cmd.exe", "/c",  "dir -d").start();

对于附加问题: reader.readLine() 正在阻塞并等待直到可以读取一行(期望行分隔符)。它 returns 仅当缓冲区已完全读取时才为空(即可以关闭)。 因此,您的 while 循环将在到达流末尾之前完成。