2009-06-23 66 views
5

是否可以使用NIO來處理來自進程的stdout?我已經與java.io一起工作,但這是一個練習,可以學習更多關於NIO的知識,並探討性能改進的可能性。是否可以將進程stdout InputStream讀入NIO ByteBuffer?

基本上我希望儘可能快地將大量文本從stdout流入緩衝區而不會阻塞,然後稍後處理該緩衝區的內容。麻煩的是,我似乎無法弄清楚正確的巫術使它與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(); 
    } 
    } 
} 
+0

你想簡單地在一個單字節緩衝區中的所有標準:以一次投入?你知道輸入流的最大長度嗎? – 2009-06-23 16:24:38

+0

我想一次將它讀入緩衝區,但是長度未知;通常在10 MB範圍內。 – Rob 2009-06-23 18:10:02

回答

5

信不信由你,我想你想的寫字節通道

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

然後當完成時

ostream.toByteArray() 

包含s要處理的字節。或者,如果你想有一個字節的緩衝區,

ByteBuffer.wrap(ostream.toByteArray()) 

我在這裏看不到你如何讓外運行的輸出,但我懷疑你的原代碼有這樣的。否則,您可能需要StreamConsumerCallable<ByteBuffer>

1

您可能希望StreamConsumer成爲Callable。

另一個非阻塞選項嘗試可能是使用番石榴的ListenableFuture給你成功和失敗回調沒有解釋你自己的錯誤。

4

我已經創建了一個開放源代碼庫,允許Java和您的子進程之間的非阻塞I/O。該庫提供了一個事件驅動的回調模型。這取決於JNA庫使用特定於平臺的本機API,例如Linux上的epoll,MacOS X上的kqueue/kevent或Windows上的IO完成端口。

該項目被稱爲NuProcess並可以在這裏找到:

https://github.com/brettwooldridge/NuProcess

相關問題