Можно ли прочитать стандартный вывод InputStream в NIO ByteBuffer?

StackOverflow https://stackoverflow.com/questions/1033653

Вопрос

Можно ли использовать 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);

Тогда когда закончите

ostream.toByteArray() 

содержит байты для обработки. Или, если вы хотите байтовый буфер,

ByteBuffer.wrap(ostream.toByteArray())

Я не вижу здесь, как вы получаете вывод за пределы runnable, но я подозреваю, что ваш исходный код имел это. В противном случае вы можете захотеть, чтобы StreamConsumer был Callable<ByteBuffer>.

Другие советы

Я создал библиотеку с открытым исходным кодом, которая позволяет неблокировать ввод-вывод между Java и вашими дочерними процессами. Библиотека предоставляет управляемую событиями модель обратного вызова. Использование библиотеки JNA для конкретной платформы зависит от библиотеки JNA, такой как epoll в Linux, kqueue / kevent в MacOS X или порты завершения ввода-вывода в Windows.

Проект называется NuProcess и его можно найти здесь:

https://github.com/brettwooldridge/NuProcess

  

вы можете захотеть, чтобы StreamConsumer был вызываемым.

Еще одна неблокирующая опция, которую можно попробовать, может заключаться в использовании ListenableFuture от Guava, обеспечивающем успешные и неудачные обратные вызовы без интерпретации собственных ошибок.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top