和其他java類一樣,緩衝區類內部也分爲成員變量和方法兩個組成部分。在這裏,成員變量稱之爲狀態變量,方法稱爲訪問方法,每一個訪問方法的執行都會改變狀態變量的值。
狀態變量
- position :指向緩衝區(底層數組)下一個空閒位置的索引,如緩衝區當前有三個元素,那麼position=3,他也同樣指明瞭緩衝區當前可用數據大小。他也是繼續向緩衝區寫數據和從緩衝區讀取數據的開始。
- limit :
變量表明還有多少數據需要取出(在從緩衝區寫入通道時),或者還有多少空間可以放入數據(在從通道讀入緩衝區時)。
position
總是小於或者等於limit
。 - capacity :
capacity
表明可以儲存在緩衝區中的最大數據容量。實際上,它指定了底層數組的大小 — 或者至少是指定了准許我們使用的底層數組的容量。limit
決不能大於capacity
。capacity不會改變,而其他兩個狀態變量會經常變動
訪問方法:會對position和limit產生影響
- flip() :limit=position;position=0;爲從緩衝區讀取數據做好準備
- clear() :limit = capacity;position=0;回到緩衝區最初始的狀態,爲往緩衝區寫數據做好準備。
- get(): 有四個變種,用於從緩衝區直接讀取數據到數組
- put():向緩衝區寫入數據
- 和基本類型對應的putXXX和getXXX方法。
以下這個例子描述了從一個緩衝區讀取數據寫入另一個緩衝區的簡單代碼:
緩衝區的創建:
- ByteBuffer buffer = ByteBuffer.allocate( 10 ); 底層使用同樣大小的數組作爲數據結構
byte array[] = new byte[10]; ByteBuffer buffer = ByteBuffer.wrap( array );//使用現有數據存放數據,查看源代碼可以發現,被wrap的數據中數據不會清空
緩衝區分片:
slice():返回position和limit直間的數組作爲底層的緩衝區,在實質上和原始緩衝區公用底層數據,相當於將緩衝區有效數值的一個視圖,對視圖的修改會影響底層數據
只讀緩衝區:
asReadOnlyBuffer():將常規緩衝區轉化爲只讀緩衝區,還是和原始緩衝區共享底層結構和緩衝區數值
直接和間接緩衝區
另一種有用的 ByteBuffer
是直接緩衝區。 直接緩衝區 是爲加快 I/O
速度,而以一種特殊的方式分配其內存的緩衝區。
實際上,直接緩衝區的準確定義是與實現相關的。Sun 的文檔是這樣描述直接緩衝區的:
給定一個直接字節緩衝區,Java 虛擬機將盡最大努力直接對它執行本機 I/O 操作。也就是說,它會在每一次調用底層操作系統的本機 I/O 操作之前(或之後),嘗試避免將緩衝區的內容拷貝到一箇中間緩衝區中(或者從一箇中間緩衝區中拷貝數據)。
直接緩衝區獲得: ByteBuffer buffer = ByteBuffer.allocateDirect( 1024 );
使用和普通緩衝區一樣使用
內存映射文件 I/O
內存映射文件 I/O 是一種讀和寫文件數據的方法,它可以比常規的基於流或者基於通道的 I/O 快得多。
內存映射文件 I/O 是通過使文件中的數據神奇般地出現爲內存數組的內容來完成的。這其初聽起來似乎不過就是將整個文件讀到內存中,但是事實上並不是這樣。一般來說,只有文件中實際讀取或者寫入的部分纔會送入(或者 映射 )到內存中。
內存映射並不真的神奇或者多麼不尋常。現代操作系統一般根據需要將文件的部分映射爲內存的部分,從而實現文件系統。Java 內存映射機制不過是在底層操作系統中可以採用這種機制時,提供了對該機制的訪問。
儘管創建內存映射文件相當簡單,但是向它寫入可能是危險的。僅只是改變數組的單個元素這樣的簡單操作,就可能會直接修改磁盤上的文件。修改數據與將數據保存到磁盤是沒有分開的。
將文件映射到內存 第 8 頁(共8 頁)
瞭解內存映射的最好方法是使用例子。在下面的例子中,我們要將一個 FileChannel
(它的全部或者部分)映射到內存中。爲此我們將使用 FileChannel.map()
方法。下面代碼行將文件的前 1024
個字節映射到內存中:
MappedByteBuffer mbb = fc.map( FileChannel.MapMode.READ_WRITE,
0, 1024 );
map()
方法返回一個 MappedByteBuffer
,它是
ByteBuffer
的子類。因此,您可以像使用其他任何 ByteBuffer
一樣使用新映射的緩衝區,操作系統會在需要時負責執行行映射。