Java NIO 學習筆記 - ByteBuffer (早期筆記)

(參考 “ibm nio入門”)

在 NIO 庫中,所有數據都是用緩衝區處理的。在讀取數據時,它是直接讀到緩衝區中的。在寫入數據時,它是寫入到緩衝區中的。任何時候訪問 NIO 中的數據,都是將它放到緩衝區中。緩衝區實質上是一個數組。通常它是一個字節數組,但是也可以使用其他種類的數組。但是一個緩衝區不僅僅是一個數組。緩衝區提供了對數據的結構化訪問,而且還可以跟蹤系統的讀/寫進程。

buffer其實只是一個美化了的數組

狀態變量

跟蹤數據的狀態情況使buffer可以自己管理數據資源

position: 其實是指從buffer讀取或寫入buffer的下一個元素位置。比如,已經寫入buffer 3個元素那那麼position就是指向第4個位置,即position設置爲3(數組從0開始計)。
limit:還有多少數據需要從buffer中取出,或還有多少空間可以放入。postition總是<=limit。
capacity: 表示buffer本身底層數組的容量。limit絕不能>capacity。
filp():作了兩件事情:1.將limit指向現在position的位置 2.將position設置爲0 (limit=position;position=0)
       這個過程可以使之前buffer寫入數據時改變的狀態變爲可以“準備讀取”。因爲之前寫到buffer中的數據就是position 到 limit-1 兩個位置之間(limit指向最後一個數據的後一個位置)。
filp
clear():
    也作了兩件事:1. limit=capacity 2.position=0
這個過程可以使buffer讀取數據時改變的狀態改變爲“清空並準備寫入”。
clear

訪問方法

以下都以bytebuffer爲例
get():
   前三個get方法是相對讀取。就是相對於位置狀態來讀取數據,並且會改變position位置狀態。
   byte get();
   ByteBuffer get(byte dst[]);//讀取bytebuffer中數據寫入 dst[]
   ByteBuffer get(byte dst[],int offset, int length);
   
   該讀取數據是絕對讀取(一個byte),即會忽略limit和position值。並完全繞過了緩衝區的狀態統計方法。
   就是說不會改變buffer內部的位置狀態。
   byte get(int index);
 
put();
   與get類似 前四個put方法是相對讀取。即受position 以及limit影響,並且會改變 position。
   ByteBuffer put( byte b );
   ByteBuffer put( byte src[] ); //從src[]寫入bytebuffer
   ByteBuffer put( byte src[], int offset, int length );
   ByteBuffer put( ByteBuffer src );
   最後一個是絕對寫入 不會影響position等位置狀態。
   ByteBuffer put( int index, byte b );
 
除了byte的讀寫還有其他類型的讀寫方法。並且他們都存在相對以及絕對兩類。
 
操作的典型使用:

高級應用

緩存區的分配和包裝

ByteBuffer.allocate(int);方法可以分配(創建)一個byte類型的buffer。
ByteBuffer.wrap(byte[]);方法可以將一個已有的byte數組包裝出一個新的bytebuffer對象。
後一種方式需要小心處理原來的那個byte數組。因爲它可以直接訪問了。

緩衝區的分片

分片就是建立“子緩衝區”。子緩衝區共享父緩衝區的一部分底層數組位置。
在某種意義上,子緩衝區就像原來的緩衝區中的一個窗口。
這樣當改變子緩衝區的內容時,父緩衝區的相應位置也會被改變。
分片操作是根據當前position以及limit的值來確定的。
buffer.position( 3 );
buffer.limit( 7 );
ByteBuffer slice = buffer.slice();

只讀緩衝區

asReadOnlyBuffer()方法可以返回一個與原buffer對象一樣的對象,只是新的buffer對象是隻讀的。

直接緩衝區

sun的定義:給定一個直接字節緩衝區,Java 虛擬機將盡最大努力直接對它執行本機 I/O 操作。也就是說,它會在每一次調用底層操作系統的本機 I/O 操作之前(或之後),嘗試避免將緩衝區的內容拷貝到一箇中間緩衝區中(或者從一箇中間緩衝區中拷貝數據)。
創建directbuffer的方式是用ByteBuffer.allocateDirect( int );方法替代ByteBuffer.allocate(int);

內存影射文件I/O

它讀寫要比其他IO快很多.
他使文件或文件的一部分由內存影射。但是隻有操作該部分位置的數據纔是以內存方式讀寫的,而不是整個文件讀入內存。(並且他是一個os的底層機制。由os底層異步完成內存與物理磁盤上的數據同步)
影射文件可以通過FileChannel對象的map方法得到。
比如以下就是將一個文件的前1024個字節影射到內存,並創建一個MappedByteBuffer對象返回出來。MappedByteBuffer是ByteBuffer的一個子類。
MappedByteBuffer mbb = fc.map( FileChannel.MapMode.READ_WRITE, start, size );

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章