我正在使用ProcessBuilder运行我们正在使用的命令行工具。在运行期间,该工具会询问2个“是/否”问题,因此通常我会回答“ y”两次,然后每次都按Enter键。我的问题是,从cmd运行该工具时,它总是会完成运行,但是当我通过Java代码运行该工具时,它有时会工作,有时会卡在while ((n = op.read(buffer)) != -1)上(使用相同的输入)。

这是我的代码。难道我做错了什么?我想念什么?谢谢。

List<String> processArgs = new ArrayList<>();
processArgs.add(0, "java");
processArgs.add(1, "-jar");
processArgs.add(2, JAR_PATH);
processArgs.add(3, "-put");
processArgs.addAll(args);
try
{
    // run tool with put
    ProcessBuilder pb = new ProcessBuilder(processArgs);
    pb.directory(new File("src\\temp"));
    pb.redirectErrorStream(true);
    Process p = pb.start();

    // write 'y' to the tool's stdin.
    String answer = "y" + System.getProperty("line.separator");
    // yes to first question
    p.getOutputStream().write(answer.getBytes());
    p.getOutputStream().flush();

    // read tool's process stdout
    this.op = new BufferedReader(new InputStreamReader(p.getInputStream()));
    StringWriter sw = new StringWriter();
    int n = 0;
    boolean answered = false;
    char[] buffer = new char[BUFFER_SIZE];
    while ((n = op.read(buffer)) != -1)
    {
        sw.write(buffer, 0, n);
        if (sw.toString().contains("second question") && !answered)
        {
            // yes to second question
            p.getOutputStream().write(answer.getBytes());
            p.getOutputStream().flush();
            answered = true;
        }
    }

    stdout = sw.toString();
    exitCode = p.waitFor();
}
catch (IOException | InterruptedException e)
{
    throw new ToolException("process had an exception:\n" + e.getMessage());
}


更新:
我更改了代码并添加了pb.redirectErrorStream(true),但是现在该过程仍然在op.read(buffer)上被阻止。当我调试时,即使我在输出流中写了两次“ y”,它似乎也卡在了第二个问题上。我使用getOutputStream()的方式不正确吗?

第二次更新:
第二个问题没有得到第二个“ y”作为答案,它导致流程等待输入。我更改了代码,因此我将显示将输入插入子流程输出流的正确方法。

最佳答案

输出和错误流被缓冲。当缓冲区填满时,程序停止等待您读取它。但是,您只能先读取输出,因此,如果错误流满了,您将陷入死锁。

一种简单的解决方案是将错误重定向到输出,这样您就只能读取一个流。即

pb.redirectErrorStream(true);


根据文档https://docs.oracle.com/javase/8/docs/api/java/lang/ProcessBuilder.html

替代方案包括;将错误写入文件,或在另一个线程中读取它。

关于java - ProcessBuilder BufferedReader read()阻塞,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42053481/

10-12 00:47
查看更多