Netty Associated -- ByteBuf


ByteBuf

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

buffer創建

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

隨機訪問索引

就像普通的原聲字節數組一樣, ByteBuf使用零基坐標(zero-based indexing). 這表示第一個字節的坐標總是0, 最后一個字節的坐標總是capacity - 1.例如, 要遍歷buffer的所有字節,你可以按下面這樣做:

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

連續訪問索引

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

可讀字節(真實內容)

這個段是真實數據儲存的地方.任何名字以start或skip開始的操作都會增加當前readerIndex他讀過的字節數.如果讀操作的參數也是一個ByteBuf, 並且沒有指定目的地坐標, 那么指定ByteBuf的writerIndex也會一起增加

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

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

可寫字節

這個段是一個等待被填滿的未定義空間.任何名字已write結尾的操作都會在當前writerIndex上寫入數據,並且將writerIndex的值增加寫入的數據數.如果寫入操作的參數也是一個ByteBuf, 並且沒有元坐標被指定, 那么指定的buffer的readerIndex也會一起增加

如果沒有組合夠的空間剩余來寫,會拋出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()回收未被使用的區域將其變為丟棄字節, 如下圖所示

 

調用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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM