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

时间:2016-01-14 11:08:21

标签: java windows process

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?

btw:我仍然想知道为什么进程的standard_ouput(stdout)是由p.getInputStream()而不是p.getOutputStream()获得的。为什么它以返回类型命名,而不是在功能之后命名?!

编辑: 附加问题: 要确保子进程在完整的stdout缓冲区上没有阻塞,需要读取输出缓冲区:

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()返回null,则缓冲区为空。如果父进程退出while循环后子进程写入stdout会怎么样?这不是导致同样的潜在死锁问题吗?

1 个答案:

答案 0 :(得分:0)

使用ProcessBuilder,每个部分都单独给出,可执行文件和args。

您应该使用:

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

有关其他问题: reader.readLine()正在阻塞并等待,直到可以读取一行(期望行分隔符)。只有当缓冲区被完全读取时才会返回null(即它可以被关闭)。 因此,在到达流的末尾之前,您的while循环将不会完成。