0

이전에 이런 질문을 받았지만 때로 사람들이 겪었을 때 다른 대답이 도움이되지 않았 음을 알고 있습니다.Java 응용 프로그램 내에서 C 콘솔 응용 프로그램과 상호 작용하는 방법

C 애플리케이션을 시작하고 몇 가지 입력을 전달하여 메뉴를 탐색해야 마침내 필요한 것을 실행할 수 있습니다. 최종 결과 (결과)는 파일로 보내지 만 중간 출력 (콘솔에 인쇄 된 메뉴 및 하위 메뉴)은 디버깅을 위해 내 Eclipse 콘솔에 인쇄 된 것이 좋을 것입니다.

사용자 Vince posted on his question 및 이후 언급 한 내용을 기반으로 다음 코드를 작성했지만 나에게 도움이되지는 않습니다.

public final class InteractWithExternalApp { 

    private static PrintWriter printOut; 
    private static BufferedReader retrieveOutput; 

    private static Process p; 

    private EvaluationTests(){} // suppressing the class constructor 

    public static void Evaluate(String paramToApp) { 
     try 
     { 
      Runtime rt = Runtime.getRuntime() ; 
      p = rt.exec("C:\\Path\\To\\Desktop\\appName " + paramToApp); 
      InputStream in = p.getInputStream() ; 
      OutputStream out = p.getOutputStream(); 

      retrieveOutput = new BufferedReader(new InputStreamReader(in)); 
      printOut = new PrintWriter(out); 

      // print menu 
      if((line = retrieveOutput.readLine()) != null) { 
      System.out.println(line); 
      } 

      // send the input choice -> 0 
      printOut.println("0"); 
      printOut.flush(); 

      // print sub-menu 
      if((line = retrieveOutput.readLine()) != null) { 
       System.out.println(line); 
      } 

      // send the input choice 
      printOut.println("A string"); 
      printOut.flush(); 

      // print sub-menu 
      if((line = retrieveOutput.readLine()) != null) { 
       System.out.println(line); 
      } 

      /* 
       Repeat this a few more times for all sub-menu options until 
       the app finally executes what's needed 
      */ 

     }catch(Exception exc){ 
      System.out.println("Err " + exc.getMessage()); 
     } 

     return; 
    } 

또한, 운동으로, 나는 here 주어진 예 다음, Windows 명령 프롬프트를 열고 그것에게 명령을 전송했습니다. cmd.exe가 잘 열렸지만, echo 명령을 전달하면 아무것도하지 못했습니다.

OutputStream stdin = p.getOutputStream(); 
InputStream stdout = p.getInputStream(); 

stdin.write(new String("echo test").getBytes()); 
stdin.flush(); 

아무도 손을 들어주지 마십시오. 내가 어디로 잘못 가고 있니?

+0

. ProcessBuilder를 사용하십시오. 공백을보다 잘 처리합니다. – Jayan

+0

@Jayan,'ProcessBuilder pb = new ProcessBuilder ("C : \\ Path \\ To \\ Desktop \\ appName", "paramToApp");와'pb.start()'와 같은 의미입니까? 공식적으로 질문에 답한 것이 아니기 때문에 그 문제가 유일한 문제인지 추측해야하며 나머지는 정상적으로 작동합니까? –

+0

예. 그것은 시작일 것입니다. – Jayan

답변

2

을 나는 100 % 확실 해요 :주의 코멘트가 표시

코드에 포장되어 필요에 따라 붕괴, 가독성 불필요하게 장황 , 나는 자바와 C 프로그램의 입력과 출력 스트림 사이의 연결에 문제가 있다고 99 % 확신하고있다. 프로그램을 시작할 수 있었지만 필요한 매개 변수를 전달할 수 없었습니다.

실제로 솔루션은 ProcessBuilder을 사용하여 왔습니다. 내가 찾은 이전 해결책으로 돌아가도록 부탁해 줘서 고맙다. 그래서 여기

최종 코드 :

public final class InteractWithExternalApp { 

private static BufferedReader inputReader, errorReader; 
private static OutputStream outputStream; 
private static PrintStream printOutputStream; 

private InteractWithExternalApp(){} // suppressing the class constructor 

public static void Evaluate(String paramToApp) { 
    System.out.println("Running evaluation tests..."); 

    try 
    { 
     ProcessBuilder pb = new ProcessBuilder("Path/to/my/C/application", "paramToApp"); 
     pb.redirectOutput(Redirect.INHERIT); 
     pb.redirectError(Redirect.INHERIT); 
     Process process = pb.start(); 

     String line; 

     errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); 
     while((line = errorReader.readLine()) != null){ 
      System.out.println(line); 
     } 

     inputReader = new BufferedReader(new InputStreamReader(process.getInputStream())); 
     while((line = errorReader.readLine()) != null){ 
      System.out.println(line); 
     } 

     outputStream = process.getOutputStream(); 
     printOutputStream = new PrintStream(outputStream); 
     printOutputStream.println("A parameter"); printOutputStream.flush(); 
     printOutputStream.println("Another parameter"); printOutputStream.flush(); 
     printOutputStream.println("And however many more I would need to finally get where I wanted"); printOutputStream.flush(); 

     inputReader.close(); 
     errorReader.close(); 
     printOutputStream.close(); 

    } catch(IOException ioe){ 
     System.out.println("Error during evaluation routine: " + ioe.getMessage()); 
    } finally { 
     System.out.println("Evaluation complete!"); 
    } 

    return; 
} 

하는 나는 아직 대답, 나는 공식적으로 여기 @Benjamin Gruenbaum 및 @samaitra, 내 감사의 표현 "투표를"충분한 명성을하지 않기 때문에 사람 그들의 해결책을 this question에 올렸습니다.

다른 사람에게도 도움이되기를 바랍니다.

0

끝에 "\ n"이 없을 때 매달려있는 readLine()의 문제입니다. 가장 단순한 IMHO 인이 고양이를 스킨 할 수있는 방법이 많이 있습니다.) ... readLine()을 사용하는 대신 nio CharBuffer를 사용하면 끝에있는 줄 바꿈이 만족 스러우며 필요한 모든 것을 잡아낼 수 있습니다 (read (CharBuffer)). 당신의 앱이 중간에 멈추는 것을 안다면, 필요한 모든 Thread.sleep() 호출을 추가하여 모든 것을 갖도록하십시오.
Thread.sleep(1000) //sleep for a sec to make sure the app started outputting
final CharBuffer cb = CharBuffer.allocate(1024 * 1024); // I set a 1mb for the buffer, but it's probably excessive boolean canPrint = true; // print menu String data; while (canPrint) { if (retrieveOutput.ready()) { cb.clear(); if (retrieveOutput.read(cb) != -1) { cb.flip(); data = cb.toString(); cb.flip(); final String[] params = data.split("\n"); //split the output back into lines (not really needed) for (final String line : params) { LOG.info(line.replace("\r", "")); // these will be there on windows but not Unix or OSX } Thread.sleep(1000) //sleep for a sec to see if more output will be added } else { canPrint = false; } } else { canPrint = false; } }

HTH, 내가 말하고 싶지 않아요

+0

안녕하세요, @nrapopor. 그냥 똑바로 해봅시다. 내가 제안한 코드가 "인쇄 메뉴"와 "인쇄 하위 메뉴"로 주석을 달았을 때의 모든 상황을 대신해야한다고 생각하십니까? –

+0

노력에 감사드립니다, @nrapopor. 나는 대답을 게시했다. 아마도 너는보고 싶을 것이다! –