Netty Associated -- ByteBuf

ByteBuf

ByteBuf是Netty的Server與Client之間通訊的數據傳輸載體.他提供了一個byte數組(byte[])的抽象視圖數組

buffer建立

咱們推薦經過一個Unpooled的幫助方法來建立新的buffer而不是經過調用獨立的構造器來建立dom

隨機訪問索引

就像普通的原聲字節數組同樣, ByteBuf使用零基座標(zero-based indexing). 這表示第一個字節的座標老是0, 最後一個字節的座標老是capacity - 1.例如, 要遍歷buffer的全部字節,你能夠按下面這樣作:spa

   ByteBuf buffer = ...;
   for (int i = 0; i < buffer.capacity(); i ++) {
       byte b = buffer.getByte(i);
       System.out.println((char) b);
   }

連續訪問索引

ByteBuf提供了兩個指針變量來支持順序讀寫操做 - readerIndex用來支持讀操做, writerIndex用來支持寫操做.下面的表格顯示了一個buffer是如何經過兩個指針分段爲三部分的3d

可讀字節(真實內容)

這個段是真實數據儲存的地方.任何名字以start或skip開始的操做都會增長當前readerIndex他讀過的字節數.若是讀操做的參數也是一個ByteBuf, 而且沒有指定目的地座標, 那麼指定ByteBuf的writerIndex也會一塊兒增長指針

若是buf沒有足夠的內容可供讀取,會拋出IndexOutOfBoundsException. 最新分配的buffer, buffer的包裝類和副本的readerIndex默認值都是0code

   // Iterates the readable bytes of a buffer.
   ByteBuf buffer = ...;
   while (buffer.readable()) {
       System.out.println(buffer.readByte());
   }

可寫字節

這個段是一個等待被填滿的未定義空間.任何名字已write結尾的操做都會在當前writerIndex上寫入數據,而且將writerIndex的值增長寫入的數據數.若是寫入操做的參數也是一個ByteBuf, 而且沒有元座標被指定, 那麼指定的buffer的readerIndex也會一塊兒增長blog

若是沒有組合夠的空間剩餘來寫,會拋出IndexOutOfBoundsException. 最新分配的buffer的writerIndex的默認值是0, 包裝類和buffer副本的writerIndex是buffer的容量索引

   // Fills the writable bytes of a buffer with random integers.
   ByteBuf buffer = ...;
   while (buffer.maxWritableBytes() >= 4) {
       buffer.writeInt(random.nextInt());
   }

 丟棄字節

這個段包含已經被讀操做讀過的字節.初始化的時候, 這個段的大小爲0,這個段的大小會隨着讀操做一直增長到writerIndex.讀字節能夠經過discardReadBytes()回收未被使用的區域將其變爲丟棄字節, 以下圖所示ip

 

調用discardReadBytes()前:內存

 

使用discardReadBytes()後:

請注意並不能保證在調用discardReadBytes()後並不能保證可寫字節的內容.可寫字節在大部分狀況下不會移動, 而且可能被徹底不一樣的數據填滿, 這取決於底層的buffer實現.

 

清除buffer索引

你能夠經過調用clear()將readerIndex和writerIndex都設爲0.這不會清除buffer內容(例如用0填充), 他僅僅是清除了兩個指針.請注意這個操做的語義和ByteBuffer.clear()是不同的

clear()前

clear()後

 

搜索操做

使用indexOf(int, int, byte)和bytesBefore(int, int, byte)能夠進行最簡單的單字節搜索.bytesBefore(byte)在你處理一個NUL-terminated字符串的時候特別有用.更復雜的搜索, 請使用forEachByte(int, int, ByteBufProcessor)和一個ByteBufProcessor的實現

 

標記和重置

每一個buffer都有兩個標記索引.一個用來保存readerIndex,另外一個用來保存writerIndex.你能夠經過調用reset()放來來重置他們中的一個.他的工做方式和InputStream中的mark和reset方法很像, 只是沒有readlimit

 

派生buffer

你能夠經過調用duplicate(), slice()或者slice(int, int)來建立一個已存在的buffer的視圖.一個派生的buffer會有單獨的readerIndex,writerIndex和標記座標, 可是他共享其餘數據.就像一個NIO的buffer同樣.

加入你須要一個全新的buffer的copy,請調用copy()方法

 

轉化爲已存在的JDK類型

Byte array

假如一個ByteBuf是有一個byte數組做爲支持的, 你能夠直接經過array()方法訪問它. 判斷一個buffer是不是被byte array做爲支持,調用hasArray()

只有堆內內存的ByteBuf是有array支持的, 若是是堆外內存的ByteBuf, 是不能經過array()獲取到數據的, 而CompositeByteBuf可能由堆內的ByteBuf和堆外的DirectByteBuf組成, 他也不能直接經過array()獲取數據

 

NIO Buffers

若是一個ByteBuf能夠被轉換爲NIO ByteBuffer, 他共享他的內容,你能夠經過nioBuffer()獲取它.判斷一個buffer可否被轉化爲NIO buffer, 使用nioBufferCount().

 

Strings

各類各樣的toString(Charset)方法將一個ByteBuf轉化爲一個String.請注意toString()並非一個轉換方法.

 

I/O Streams

請看ByteBufInputStream和ByteBufOutputStream

相關文章
相關標籤/搜索