簡體   English   中英

ProcessBuilder BufferedReader read()阻塞

[英]ProcessBuilder BufferedReader read() blocking

我正在使用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

替代方案包括; 將錯誤寫入文件,或在另一個線程中讀取它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM