【问题标题】:Java reading standard output from an external program using inputstreamJava使用输入流从外部程序读取标准输出
【发布时间】:2009-07-06 20:01:55
【问题描述】:

我正在尝试开发一个读取外部程序标准输出的类(使用 Process 的实例 Runtime.getRuntime().exec(cmdLine, env, dir))。 该程序在此过程中接受用户输入,并且在给出有效输入之前不会继续;这似乎导致我尝试读取其输出的方式出现问题:

    egm.execute(); // run external the program with specified arguments
    BufferedInputStream stdout = new BufferedInputStream(egm.getInputStream());
    BufferedInputStream stderr = new BufferedInputStream(egm.getErrorStream());
    BufferedOutputStream stdin = new BufferedOutputStream(egm.getOutputStream());



    int c; //standard output input stream
    int e; //standadr error input stream

    while((c=stdout.read()) != -1) //<-- the Java class stops here, waiting for input? 
    {
        egm.processStdOutStream((char)c); 
    }
    while((e=stderr.read()) != -1)
    {
        egm.processStdErrStream((char)e);
    }
    //...

我该如何解决这个问题,以便程序接受有效的输入并继续?解决这个问题的任何帮助都会很棒!

【问题讨论】:

    标签: java io


    【解决方案1】:

    必须同时使用程序的 stdout 和 stderr 以避免阻塞情况。

    有关更多信息,请参阅this article,特别注意StreamGobbler 机制,该机制在单独的线程中捕获 stdout/err。这对于防止阻塞至关重要,如果您没有正确执行,则会导致许多错误!

    【讨论】:

      【解决方案2】:

      在这种情况下,您应该有单独的线程来读取 InputStream 和 ErrStream。

      您可能还想执行以下操作:

      public void run() {
        while( iShouldStillBeRunning ) {
             int c;
             while( stdout.available() > 0 && ((c=stdout.read()) != -1)) {
               egm.processStdOutStream((char)c);
             }
      
           Thread.sleep(100);
        }
      }
      

      因为你会在stdout.read() 被屏蔽,直到有输入。

      【讨论】:

        【解决方案3】:

        一方面,如果它正在写入 error 流并耗尽缓冲区,这可能会阻塞 - 在输出流完全完成之前,您不会从错误流中读取。

        接下来,您说在此过程中需要用户输入 - 您是否通过写信给 stdin给予任何用户输入?如果它正在等待输入,你应该适当地写信给stdin,然后刷新它。

        【讨论】:

          【解决方案4】:

          你没有在你的问题中说当你尝试运行它时实际发生了什么。请更新详细说明会发生什么,以及您期望会发生什么。告诉我们命令是什么的奖励积分。

          另外,这是 UNIX/Linux 还是 Windows?如果这是 UNIX/Linux(或其他一些 POSIX 平台),出于安全原因,程序可能会在 /dev/console 而不是 /dev/stdin 上寻找输入。

          【讨论】:

            【解决方案5】:

            为了其他寻求此类问题解决方案的人的利益,我只想补充一点,我遇到了一个非常相似的问题。但就我而言,该程序也在等待单行输入。因此需要涉及三个线程来异步处理所有三个通道。

            不写入输出(即执行程序的标准输入)导致输入(即执行程序的输出)没有被完全捕获。写入它会挂起进程。

            解决方案是 Jon Skeet 的三个词:“并冲洗它”。添加冲洗后,没有挂起。谢谢!

            【讨论】:

              猜你喜欢
              • 2010-11-09
              • 1970-01-01
              • 2012-10-31
              • 1970-01-01
              • 2012-09-25
              • 1970-01-01
              • 2012-07-05
              • 2018-03-05
              • 1970-01-01
              相关资源
              最近更新 更多