Java 是否可以将进程stdout InputStream读入NIO ByteBuffer?

Java 是否可以将进程stdout InputStream读入NIO ByteBuffer?,java,inputstream,nio,bytebuffer,Java,Inputstream,Nio,Bytebuffer,是否可以使用NIO处理进程中的标准输出?我已经在使用java.io了,但是这是一个练习,可以学习更多关于NIO的知识,并探索性能改进的可能性 基本上,我希望尽可能快地将大量文本从标准输出流到一个缓冲区,而不阻塞,然后稍后处理该缓冲区的内容。问题是,我似乎无法找出正确的巫术来让它与NIO合作。这就是我现在的处境: ProcessBuilder pb = new ProcessBuilder( ... ); Process p = pb.start(); stdout = new StreamCon

是否可以使用NIO处理进程中的标准输出?我已经在使用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();
    }
  }
}

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

ByteArrayOutputStream ostream = new ByteArrayOutputStream(<some large number>);
WritableByteChannel destination = Channels.newChannel(ostream);
包含要处理的字节。或者,如果需要字节缓冲区

ByteBuffer.wrap(ostream.toByteArray())
我不知道您是如何在runnable之外获得输出的,但我怀疑您的原始代码中有这个功能。否则,您可能希望
StreamConsumer
是一个
可调用的

您可能希望StreamConsumer是可调用的


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

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

项目名为,可在以下位置找到:


您想将所有标准输入一次放入一个单字节缓冲区吗?您知道输入流的最大长度吗?我想一次将其读入缓冲区是的,但长度未知;通常在10MB的范围内。建议使用Callable。真不敢相信我竟然忘了。这很有魅力。
ByteBuffer.wrap(ostream.toByteArray())