2009-08-22 36 views
3

我想從TCP數據流中讀取一個字符串,字符長度後面跟着實際數據。在Python中,我會做Java NIO:讀取可變大小的數據塊

length = ord(stream.read(1)) 
data = stream.read(length) 

如何在Java NIO中執行相同操作?我有一個緩衝區(容量257)

stream.read(buffer); // cannot specify a size here 
int length = buffer.get(); 
byte[] data = new byte[length]; 
buffer.get(data); 

不幸的是,這並不工作:的get()調用read 過去的緩衝區中的數據:-(

我可能需要一些組合的翻轉,倒帶,復位等,但我不知道它。

+0

什麼樣的對象是'stream'在Java的例子嗎? – Bkkbrad 2009-08-22 21:01:41

+0

這是一個SocketChannel。 – 2009-08-22 22:08:22

回答

5

如果stream是一個SocketChannelbufferByteBuffer,你可以做到以下幾點:

//assuming buffer is a ByteBuffer 
buffer.position(0); 
buffer.limit(1); 
while (buffer.hasRemaining()) { 
    stream.read(buffer); 
} 
buffer.rewind(); 

//get the byte and cast it into the range 0-255 
int length = buffer.get() & 0xFF; 
buffer.clear(); 
buffer.limit(length); 
while (buffer.hasRemaining()) { 
    stream.read(buffer); 
} 
buffer.rewind(); 
//the buffer is now ready for reading the data from 
+0

謝謝,這應該很好 - 雖然看起來相當複雜。 – 2009-08-22 22:10:21

+1

詳細,不復雜。 – 2009-08-25 15:10:06

+0

其實並不那麼簡單,人們必須記住,它不需要一次接收所有字節,或者可能一次收到多個消息。 – 2014-06-08 09:04:26

0

我建議你看看java.nio.channel.GatheringByteChannel和DatagramChannel。你需要指定一個數據報爲您的需求。

這就是wh在你的Python例子中已經完成了(第一個字節表示有效載荷長度,使用這個長度讀取playload),這看起來真的很容易出錯(!)。

數據報是數據流的規範。它將你的流分成邏輯上的包。因此,更好的策略是首先發送一個有效載荷數據包,它指出有效載荷的長度(以及包的大小)。編輯:當然,流的兩端必須使用相同的協議/數據報語言。

+0

我無法理解您的建議。 GatheringByteChannel是一個已經由我已經使用的SocketChannel實現的接口--AFAIU,這是用於TCP的標準通道。 DatagramChannel是無關緊要的,因爲這是UDP,而我正在做TCP。我也看不出爲什麼有一個協議首先發送長度,然後有效負載容易出錯 - 例如,HTTP 1.1就是這樣工作的。 – 2009-08-22 22:07:44

+0

我錯過了您的問題的一些細節。以爲分配問題比ByteBuffer的方法更多;) 無論如何,如果你的有效負載不超過255字節,Bkkbrad的解決方案是直截了當的。 – cafebabe 2009-08-22 22:57:11

相關問題