NIO學習筆記——Buffer的創建與複製

Buffer的創建

新的緩衝區是由分配或包裝操作創建的。分配操作創建一個緩衝區對象並分配一個私有的空間來儲存容量大小的數據元素。包裝操作創建一個緩衝區對象但是不分配任何空間來儲存數據元素。它使用您所提供的數組作爲存儲空間來儲存緩衝區中的數據元素,例如

CharBuffer charBuffer = CharBuffer.allocate (100);

這段代碼隱含地從堆空間中分配了一個 char 型數組作爲備份存儲器來儲存 100 個 char變量。如果您想提供您自己的數組用做緩衝區的備份存儲器,請調用 wrap()函數

char [] myArray = new char [100];
CharBuffer charbuffer = CharBuffer.wrap (myArray);

這段代碼構造了一個新的緩衝區對象,但數據元素會存在於數組中。這意味着通過調用put()函數造成的對緩衝區的改動會直接影響這個數組,而且對這個數組的任何改動也會對這個緩衝區對象可見。帶有 offset 和 length 作爲參數的 wrap()函數版本則會構造一個按照您提供的 offset 和 length參數值初始化位置和上界的緩衝區。這樣做:

CharBuffer charbuffer = CharBuffer.wrap (myArray, 12, 42);

創建了一個 position 值爲 12, limit 值爲 54,容量爲 myArray.length 的緩衝區。
我們用來做例子的CharBuffer 提供了一對其它緩衝區類沒有的有用的便捷的函數

public abstract class CharBuffer
extends Buffer implements CharSequence, Comparable
{
// This is a partial API listing38
public static CharBuffer wrap (CharSequence csq)
public static CharBuffer wrap (CharSequence csq, int start,
int end)
}

Wrap()函數創建一個只讀的備份存儲區是 CharSequence 接口或者其實現的的緩衝區對象charsequence 描述了一個可讀的字符流

CharBuffer charBuffer = CharBuffer.wrap ("Hello World");

三個參數的 wrap()函數版本使用 start 和 end 下標參數來描述傳入的 CharSequence對象的子序列。這是一個方便的類似於調用了 CharSequence.subsequence()函數的轉
換。 Start 參數是序列中使用的第一個字符, end 是最後一個字符的下標值加 1

Buffer的複製

當一個管理其他緩衝器所包含的數據元素的緩衝器被創建時,這個緩衝器被稱爲視圖緩衝器。視圖存儲器總是通過調用已存在的存儲器實例中的函數來創建。使用已存在的存儲器實例中的工廠方法意味着視圖對象爲原始存儲器的內部實現細節私有。數據元素可以直接存取,無論它們是存儲在數組中還是以一些其他的方式,而不需經過原始緩衝區對象的 get()/put()API。
我們以 CharBuffer 爲例,同樣的操作可被用於任何基本的緩衝區類型

public abstract class CharBuffer
extends Buffer implements CharSequence, Comparable
{
// This is a partial API listing
public abstract CharBuffer duplicate( );
public abstract CharBuffer asReadOnlyBuffer( );
public abstract CharBuffer slice( );
}

Duplicate()函數創建了一個與原始緩衝區相似的新緩衝區。兩個緩衝區共享數據元39素,擁有同樣的容量,但每個緩衝區擁有各自的位置,上界和標記屬性。對一個緩衝區內的數據元素所做的改變會反映在另外一個緩衝區上。這一副本緩衝區具有與原始緩衝區同樣的數據視圖。如果原始的緩衝區爲只讀,或者爲直接緩衝區,新的緩衝區將繼承這些屬性。複製一個緩衝區會創建一個新的 Buffer 對象,但並不複製數據。原始緩衝區和副本都會操作同樣的數據元素。
我們可以使用asReadOnlyBuffer()函數來生成一個只讀的緩衝視圖。這與duplicate()相同,除了這個新的緩衝區不允許使用 put(),並且其 isReadOnly()函數將會返回true。 對這一隻讀緩衝區的put()函數的調用嘗試會導致拋出ReadOnlyBufferException 異常。
如果一個只讀的緩衝區與一個可寫的緩衝區共享數據,或者有包裝好的備份數組,那麼對這個可寫的緩衝區或直接對這個數組的改變將反映在所有關聯的緩衝區上,包括只讀緩衝區
分割緩衝區與複製相似,但 slice()創建一個從原始緩衝區的當前位置開始的新緩衝區,並且其容量是原始緩衝區的剩餘元素數量( limit-position)。這個新緩衝區與原始緩衝區共享一段數據元素子序列。分割出來的緩衝區也會繼承只讀和直接屬性。

CharBuffer buffer = CharBuffer.allocate (8);
buffer.position(3).limit (5);
CharBuffer sliceBuffer = buffer.slice();

要創建一個映射到數組位置 12-20( 9 個元素)的 buffer 對象

char [] myBuffer = new char [100];
CharBuffer cb = CharBuffer.wrap(myBuffer);
cb.position(12).limit(21);
CharBuffer sliced = cb.slice();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章