2009-06-23 7 views
5

NIOを使用してプロセスからstdoutを処理することはできますか?私はjava.ioを使って作業していますが、これはNIOについてもう少し学び、パフォーマンスの向上の可能性を探る練習の一環です。Process stdout InputStreamをNIO ByteBufferに読み込むことはできますか?

基本的には、大量のテキストをブロックせずにできるだけ速くstdoutからバッファにストリーミングして、そのバッファの内容を後で処理したいとします。問題は、NIOとうまく連携するための正しいブードゥーを理解できないようです。

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(); 
    } 
    } 
} 
+0

は、あなたは、単に一度に単一バイトのバッファ内のすべての標準入力を持つようにしたいですか?あなたは入力ストリームの最大長を知っていますか? –

+0

私は一度にすべてをバッファーに読み込みたいですが、長さは不明です。しかし、典型的には10MBの範囲である。 – Rob

答えて

5

信じられないかもしれませんが、私はあなたが欲しい、書き込み可能なバイトチャネルが

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

だと思う:

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

クラスStreamConsumerは次のようになります。私は今だところですその後、完了時

ostream.toByteArray() 

処理するバイト数。それとも、あなたはバイトのバッファ、

ByteBuffer.wrap(ostream.toByteArray()) 

をしたい場合、私はあなたが実行可能な外の出力を取得する方法ここでは表示されませんが、私はあなたの元のコードがそれを持っていた疑いがあります。それ以外の場合は、StreamConsumerCallable<ByteBuffer>にすることもできます。

+1

Callableを使用する優れた提案。私はそれを忘れていたとは信じられません。これは魅力的に機能しました。 – Rob

1

StreamConsumerを呼び出し可能にすることができます。

もう1つの非ブロッキングオプションは、GuavaのListenableFutureを使用して、自分自身のエラーを解釈せずに成功と失敗のコールバックを与えることです。

4

私はJavaとあなたの子プロセスの間の非ブロックI/Oを可能にするオープンソースライブラリを作成しました。ライブラリはイベントドリブンコールバックモデルを提供します。 Linuxのepoll、MacOS Xのkqueue/kevent、WindowsのIO完了ポートなど、プラットフォーム固有のネイティブAPIを使用するJNAライブラリに依存します。

プロジェクトがNuProcessと呼ばれ、ここで見つけることができます:

https://github.com/brettwooldridge/NuProcess