Frage

Ist es möglich, NIO zu verwenden, um die Standardausgabe von einem Prozess zu verarbeiten? Ich habe es mit java.io arbeiten, aber das ist etwas, von einer Übung ein bisschen mehr über NIO zu lernen und die Möglichkeit, Performance-Verbesserungen zu erkunden.

Grundsätzlich mag ich von stdout in einen Puffer so schnell wie möglich ein großes Volumen von Text streamen, ohne zu blockieren, und dann den Inhalt dieses Puffers verarbeitet später. Das Problem ist, ich kann nicht das Recht Voodoo scheint, um herauszufinden, um es mit NIO zu arbeiten. Dies ist, wo ich jetzt bin:

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

Die Klasse StreamConsumer sieht wie folgt aus:

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();
    }
  }
}
War es hilfreich?

Lösung

Ob Sie es glauben oder nicht, ich glaube, das beschreibbare Byte Kanal Sie wollen, ist

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

Dann, wenn Sie fertig

ostream.toByteArray() 

enthält das Bytes zu verarbeiten. Oder, wenn Sie einen Bytepuffer wollen,

ByteBuffer.wrap(ostream.toByteArray())

ich nicht hier sehen Sie, wie Sie die Ausgabe außerhalb des runnable bekommen, aber ich vermute, Ihre Original-Code, dass hatte. Andernfalls könnten Sie die StreamConsumer ein Callable<ByteBuffer> zu sein.

Andere Tipps

Ich habe eine Open-Source-Bibliothek erstellt, die ermöglichen, nicht blockierende E / A zwischen Java und Ihrem Kind Prozessen. Die Bibliothek bietet ein ereignisgesteuerte Callback-Modell. Es hängt von der JNA Bibliothek plattformspezifischen nativen APIs wie epoll auf Linux zu verwenden, kqueue / kevent auf MacOS X oder IO Completion Ports unter Windows.

Das Projekt nennt NuProcess und hier gefunden werden kann:

https://github.com/brettwooldridge/NuProcess

  

Sie können die StreamConsumer wollen ein Callable sein.

Eine weitere, nicht blockierende Option versuchen könnte sein Guava der ListenableFuture verwenden Sie Erfolg und Misserfolg Rückrufe geben ohne Fehler der eigenen Interpretation.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top