是否可以将 Process stdout InputStream 读入 NIO ByteBuffer?

Posted

技术标签:

【中文标题】是否可以将 Process stdout InputStream 读入 NIO ByteBuffer?【英文标题】:Is it possible to read the Process stdout InputStream into an NIO ByteBuffer? 【发布时间】:2009-06-23 16:17:42 【问题描述】:

是否可以使用 NIO 来处理来自 Process 的 stdout?我让它与 java.io 一起工作,但这是一个练习,可以更多地了解 NIO 并探索性能改进的可能性。

基本上,我想尽可能快地将大量文本从标准输出流式传输到缓冲区而不会阻塞,然后再处理该缓冲区的内容。问题是,我似乎无法找到合适的巫术来让它与 NIO 一起工作。这就是我现在的位置:

ProcessBuilder pb = new ProcessBuilder( ... );
Process p = pb.start();
stdout = new StreamConsumer(p.getInputStream());
new Thread(stdout).start();
// other stuff omitted for brevity

StreamConsumer 类如下所示:

class StreamConsumer implements Runnable

  private InputStream is;

  public StreamConsumer(InputStream is)
  
    this.is = is;
  

  public void run()
  
    try
    
      ReadableByteChannel source = Channels.newChannel(is);

      // Is it possible get a channel to a ByteBuffer 
      // or MappedByteBuffer here?
      WritableByteChannel destination = ??;
      ByteBuffer buffer = ByteBuffer.allocateDirect(128 * 1024);

      while (source.read(buffer) != -1)
      
        buffer.flip();
        while (buffer.hasRemaining())
        
          destination.write(buffer);
        
        buffer.clear();
      

      source.close();
      destination.close();
    
    catch (IOException e)
    
      e.printStackTrace();
    
  

【问题讨论】:

您想一次简单地将所有标准输入放在一个字节缓冲区中吗?你知道输入流的最大长度吗? 我想一次将其读入缓冲区,是的,但长度未知;不过通常在 10 MB 范围内。 【参考方案1】:

我创建了一个开源库,它允许在 java 和您的子进程之间进行非阻塞 I/O。该库提供了一个事件驱动的回调模型。它依赖于 JNA 库来使用特定平台的原生 API,例如 Linux 上的 epoll、MacOS X 上的 kqueue/kevent 或 Windows 上的 IO Completion Ports。

该项目名为NuProcess,可在此处找到:

https://github.com/brettwooldridge/NuProcess

【讨论】:

【参考方案2】:

信不信由你,我认为你想要的可写字节通道是

ByteArrayOutputStream ostream = new ByteArrayOutputStream(<some large number>);
WritableByteChannel destination = Channels.newChannel(ostream);

完成后

ostream.toByteArray() 

包含要处理的字节。或者,如果你想要一个字节缓冲区,

ByteBuffer.wrap(ostream.toByteArray())

我在这里看不到您如何在可运行文件之外获得输出,但我怀疑您的原始代码有这种情况。否则,您可能希望 StreamConsumer 成为 Callable&lt;ByteBuffer&gt;

【讨论】:

使用 Callable 的绝佳建议。我不敢相信我忘记了这一点。这就像一个魅力。【参考方案3】:

您可能希望 StreamConsumer 成为 Callable。

另一个可以尝试的非阻塞选项可能是使用 Guava 的 ListenableFuture 为您提供成功和失败回调,而无需解释您自己的错误。

【讨论】:

以上是关于是否可以将 Process stdout InputStream 读入 NIO ByteBuffer?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将subprocess.Popen的stdout重新连接到sys.stdout? (python3)

转换流以将字符串添加到每一行

如何将字符串写入Scala Process?

获取 NodeJS 程序退出码

进程替换 - Node.js child_process

child_process 执行系统shell命令