[英]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.