2017-02-05 4 views
0

우리가 사용하고있는 명령 행 도구를 실행하기 위해 ProcessBuilder을 사용하고 있습니다. 도구를 실행하는 동안 도구는 2 개의 예/아니오 질문을하기 때문에 대개 저는 'y'로 두 번 응답 한 다음 매번 Enter 키를 누릅니다. 내 문제는이 도구는 cmd에서 실행될 때 도구가 항상 실행되지만 Java 코드를 통해 실행하면 가끔씩 작동하고 가끔씩 while ((n = op.read(buffer)) != -1) (같은 입력으로)에 걸릴 수 있습니다.ProcessBuilder BufferedReader read() blocking

여기 내 코드입니다. 내가 뭔가 잘못하고 있는거야? 내가 뭘 놓치고 있니? 감사.

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()); 
} 

UPDATE

: 나는 내 코드를 변경하고 pb.redirectErrorStream(true)을 추가,하지만 지금은 프로세스가 여전히 op.read(buffer)에서 차단됩니다. 디버깅 할 때 출력 스트림에 'y'를 두 번 써도 두 번째 질문에서 멈추는 것 같습니다. getOutputStream()을 잘못 사용하고 있습니까?

두 번째 질문 : 두 번째 질문에서 두 번째 'y'가 답으로 표시되지 않아 입력 대기 프로세스가 발생했습니다. 나는 서브 프로세스 outputstream에 입력을 삽입하는 적절한 방법을 보여주기 위해 코드를 변경했다.

답변

2

출력 및 오류 스트림이 버퍼링됩니다. 버퍼가 가득 차면 프로그램 읽기를 기다립니다. 그러나 오류 스트림이 가득 차면 교착 상태가 발생하므로 출력을 먼저 읽어야합니다.

간단한 해결책은 오류를 출력으로 리디렉션하여 읽을 스트림을 하나만 사용하는 것입니다. 즉

https://docs.oracle.com/javase/8/docs/api/java/lang/ProcessBuilder.html

대안 포함 문서 당으로서

pb.redirectErrorStream(true); 

; 파일에 오류를 쓰거나 다른 스레드에서 읽는 것.

+0

감사합니다. Peter, 도움을 받았지만 여전히 read()에서 차단됩니다. 내 업데이트를 참조하십시오. – gamlieldor

+0

@ gamlieldor 출력이 출력 될 때 출력하는 것이 좋습니다. 우리가 입력을 기다릴 가능성이 가장 큽니다. –

+0

나는 네가 옳았고, 두 번째 질문에 대한 입력을 기다리고있다. 첫 번째 질문에 대해서는 한 번, 두 번째 질문에 대해서는 한 번 'y'답변을 사용하도록 어떻게 만들 수 있습니까? pb 입력을 'y'라는 파일을 새 줄로 구분하여 리디렉션하려고했지만 도움이되지 않았습니다. – gamlieldor