tags:

views:

477

answers:

1

Is it possible to use NIO to process the stdout from a Process? I have it working with java.io, but this is something of an exercise to learn a bit more about NIO and to explore the possibility of performance improvements.

Basically I want to stream a large volume of text from stdout into a buffer as fast as possible without blocking, and then process the contents of that buffer later. The trouble is, I can't seem to figure out the right voodoo to make it work with NIO. This is where I am right now:

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

The class StreamConsumer looks like this:

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();
    }
  }
}
+3  A: 

Believe it or not, I think the writable byte channel you want is

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

Then when done

ostream.toByteArray()

contains the bytes to process. Or, if you want a byte buffer,

ByteBuffer.wrap(ostream.toByteArray())

I don't see here how you get the output outside the runnable, but I suspect your original code had that. Otherwise you might want the StreamConsumer to be a Callable<ByteBuffer>.

Kathy Van Stone
Excellent suggestion to use Callable. I can't believe I forgot about that. This worked like a charm.
Rob