代码之家  ›  专栏  ›  技术社区  ›  wmitchell

Java似乎没有读取我的Perl管道输出的时间,并填补了

  •  1
  • wmitchell  · 技术社区  · 15 年前

    我有以下代码片段调用了一个Perl脚本,该脚本将写入stderr和stdout。 我一直遵循建议的过程,例如在Perl脚本中自动刷新stdout和stderr,并使用streamgobbler线程。我注意到这在某种程度上有助于解决我的问题,但是在Perl脚本生成大量输出的时候,它仍然会填满管道并挂起。唯一能阻止这种情况的是将以下内容添加到我的Perl脚本中,但是很明显我希望输出结果,所以这不是一个选项。

    更新& gt;

    另一个有趣的现象是,当我在Linux中cat/proc/pid/fd/pipe时,它会导致读取管道。这似乎是在转储管道的内容,这意味着我的Perl进程可以再次对其进行写入,从而完成。因此,我的Java进程不能正确地读取进程输出流。

    Perl:

    close STDOUT 
    close STDERR
    

    我的Java看起来像下面这样

       parserProcess = run.exec(config.getCMDArray(),env);
    
    StreamGobbler errorGobbler = new StreamGobbler(parserProcess.getErrorStream(), "ERROR");
    
      // any output?
         StreamGobbler outputGobbler = new StreamGobbler(parserProcess.getInputStream(), "OUTPUT");
    
      // kick them off
         errorGobbler.start();
         outputGobbler.start();
    

    其中streamgobler是->

    class StreamGobbler extends Thread
    {
        InputStream is;
        String type;
    
    StreamGobbler(InputStream is, String type)
    {
        this.is = is;
        this.type = type;
    }
    
    public void run()
    {
        try
        {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
                System.out.println(type + ">" + line);    
            } catch (IOException ioe)
              {
                ioe.printStackTrace();  
              }
    }
    }
    
    
    
     String line="";
    
     status = parserProcess.waitFor();
    

    提前谢谢

    1 回复  |  直到 15 年前
        1
  •  2
  •   Carl Smotricz    15 年前

    我认为你在描述Perl和Java应用程序的正常行为。管道后面缓冲区的实际大小取决于未定义/OS,但可能只有1KB或16KB。对于输出生成过程来说,在其文本被消耗之前进行阻塞是很好和明智的;另一种选择是什么?为管道缓冲区分配更大的内存量?

    如果您使用上面的代码进行实验,那么您的处理速度受到Java控制台输出的瓶颈,即 System.out.println() 电话。我想,如果你评论打印出来(只是为了测试),你会看到Java很快地把Perl输出弄糊涂了。