對於緩沖區來說最重要的操作就是讀寫操作緩沖區提供了兩種方法來讀寫緩沖區中的數據getput方法和array方法而getput方法可以有三種讀寫數據的方式按順序讀寫單個數據在指定位置讀寫單個數據和讀寫數據塊除了上述的幾種讀寫數據的方法外CharBuffer類還提供了用於專門寫字符串的put和append方法在本文及後面的文章中將分別介紹這些讀寫緩沖區的方法
雖然使用allocate方法創建的緩沖區並不是一次性地分配內存空間但我們可以從用戶地角度將一個緩沖區想象成一個長度為capacity的數組當緩沖區創建後和數組一樣緩沖區的大小(capacity值)將無法改變也無法訪問緩沖區外的數據如下面的代碼創建了一個大小為的字節緩沖區
ByteBuffer byteBuffer = ByteBufferallocate()
對於byteBuffer來說只能訪問屬於這個緩沖區的六個字節的數據如果超過了這個范圍將拋出一個BufferOverflowException異常這是一個運行時錯誤因為這個錯誤只能在程序運行時被發現
既然緩沖區和數組類似那麼緩沖區也應該象數組一樣可以標識當前的位置緩沖區的position方法為我們提供了這個功能position方法有兩種重載形式它們的定義如下
public final int position()
public final Buffer position(int newPosition)
第一個重載形式用來獲取緩沖區的當前位置在創建緩沖區後position的初始值是也就是緩沖區第一個元素的位置當從緩沖區讀取一個元素後position的值加我們從這一點可以看出position方法返回的位置就是當前可以讀取的元素的位置position的取值范圍從到capacity – 如果position的值等於capacity說明緩沖區當前已經沒有數據可讀了
position方法的第二個重載形式可以設置緩沖區的當前位置參數newPosition的取值范圍是 <= newPosition < capacity如果newPosition的值超出這個范圍position方法就會拋出一個IllegalArgumentException異常
在大多數情況下不需要直接控制緩沖區的位置緩沖區類提供的用於讀寫數據的方法可以自動地設置緩沖區的當前位置在緩沖區類中get和put方法用於讀寫緩沖區中的數據get和put方法的定義如下
ByteBuffer類的get和put方法
public abstract byte get()
public abstract ByteBuffer put(byte b)
IntBuffer類的get和put方法
public abstract int get()
public abstract IntBuffer put(int i)
其他五個緩沖區類中的get和put方法定義和上面的定義類似只是get方法返回相應的數據類型而put方法的參數是相應的數據類型並且返回值的類型是相應的緩沖區類
每當put方法向緩沖區寫入一個數據後緩沖區的當前位置都會加如果緩沖區的當前位置已經等於capacity調用put方法就會拋出一個javanioBufferOverflowException異常在緩沖區未初賦值的區域將被填充使用get方法可以得到緩沖區當前位置的數據並使緩沖區的當前位置加和put方法一樣在緩沖區當前位置等於capacity時使用get方法也會拋出javanioBufferOverflowException異常緩沖區的初始狀態如圖所示
圖 緩沖區的初始狀態
從圖可以看出在緩沖區創建之初當前的位置和緩沖區中的數據都為當使用如下語句向緩沖區中寫入數據後緩沖區當前狀態如圖所示
byteBufferput((byte))
byteBufferput((byte))
圖 緩沖區的當前狀態
當緩沖區的當前位置如圖所示時使用put和get方法將會拋出上述的BufferOverflowException異常
圖 當前位置處於緩沖區尾
如果要使用get方法得到緩沖區中的指定數據
必須將緩沖區的當前位置移動到指定的位置
我們可以使用position方法將當前位置移到緩沖區的任何位置
如下面的代碼將圖
所示的緩沖區的當前位置設為
並用get方法獲得位置
的數據
byteBuffer
position(
)
System
out
println(byteBuffer
get())
上面的代碼將輸出
緩沖區的當前位置為除了使用position方法
也可以使用rewind方法將緩沖區的當前位置設為
rewind方法的定義如下
public final Buffer rewind()
在圖
所示的緩沖區狀態下調用rewind方法
就會得到如圖
的緩沖區狀態
圖 調用rewind方法後的緩沖區狀態
接下來讓我們執行如下語句
Systemoutprintln(byteBufferget())
緩沖區的狀態將如圖所示
圖 調用get方法後的緩沖區狀態
緩沖區除了position和capacity外還提供了一個標識來限制緩沖區可訪問的范圍這個標識就是limitlimit和position一樣在緩沖區類中也提供了兩個重載方法用於獲得和設置limit的值limit方法的定義如下
public final int limit()
public final Buffer limit(int newLimit)
在初始狀態下緩沖區的limit和capacity值相同但limit和capacity的區別是limit可以通過limit方法進行設置而capacity在創建緩沖區時就已經指定了並且不能改變(在上面所講的position方法的newPosition參數的取值范圍時曾說是 <= newPosition < capacity其實嚴格地說應是 <= newPosition < limit)limit的其他性質和capacity一樣如在圖所示的緩沖區狀態中將limit的值設為就變成了圖所示的狀態
圖 將limit設為的緩沖區狀態
在這時position的值等於limit就不能訪問緩沖區的當前數據也就是說不能使用get和put方法否則將拋出BufferOverflowException異常由於使用allocate創建的緩沖區並不是一次性地分配內存空間因此可以將緩沖區的capacity設為很大的值如M緩沖區過大可能在某些環境中會使系統性能降低(如在PDA或智能插秧機中)因此可以使用limit方法根據具體的情況來限定緩沖區的大小當然limit還可以表示緩沖區中實際的數據量這將在後面講解下面的代碼演示了如何使用limit方法來枚舉緩沖區中的數據
while(byteBufferposition() < byteBufferlimit())
Systemoutprintln(byteBufferget())
我們還可以用flip和hasRemaining方法來重寫上面的代碼
flip方法將limit設為緩沖區的當前位置
當limit等於position時
hasRemaining方法返回false
而則返回true
flip和hasRemaining方法的定義如下
public final Buffer flip()
public final boolean hasRemaining()
下面的代碼演示了如何使用hasRemaining方法來枚舉緩沖區中的數據
while(byteBuffer
hasRemaining())
System
out
println(byteBuffer
get())
如果從緩沖區的第一個位置依次使用put方法向緩沖區寫數據
當寫完數據後
再使用flip方法
這樣limit的值就等於緩沖區中實際的數據量了
在網絡中傳遞數據時
可以使用這種方法來設置數據的結束位置
為了回顧上面所講內容
下面的代碼總結了創建緩沖區
讀寫緩沖區中的數據
設置緩沖區的limit和position的方法
package net;
import java
nio
*;
public class GetPutData
{
public static void main(String[] args)
{
// 創建緩沖區的四種方式
IntBuffer intBuffer = IntBuffer
allocate(
)
ByteBuffer byteBuffer = ByteBuffer
allocateDirect(
)
CharBuffer charBuffer = CharBuffer
wrap(
abcdefg
)
DoubleBuffer doubleBuffer = DoubleBuffer
wrap(new double[] {
})
// 向緩沖區中寫入數據
intBuffer
put(
)
intBuffer
put(
)
System
out
println(
intBuffer的當前位置
+ intBuffer
position())
intBuffer
position(
)
// 將緩沖區的當前位置設為
System
out
println(intBuffer
get())
// 輸出緩沖區的當前數據
intBuffer
rewind()
// 將緩沖區的當前位置設為
System
out
println(intBuffer
get())
// 輸出緩沖區的當前數據
byteBuffer
put((byte)
)
byteBuffer
put((byte)
)
byteBuffer
flip()
// 將limit設為position
在這裡是
byteBuffer
rewind()
while(byteBuffer
hasRemaining()) // 枚舉byteBuffer中的數據
System
out
print(byteBuffer
get() +
)
while(charBuffer
hasRemaining()) // 枚舉charBuffer中的數據
System
out
print(charBuffer
get() +
)
// 枚舉doubleBuffer中的數據
while(doubleBuffer
position() < doubleBuffer
limit())
System
out
print(doubleBuffer
get() +
)
}
}
運行結果
intBuffer的當前位置
a b c d e f g
注意
如果必須使用緩沖區的大小來讀取緩沖區的數據
盡量不要使用capacity
而要使用limit
如盡量不要寫成如下的代碼
while(byteBuffer
position() < byteBuffer
capacity())
System
out
println(byteBuffer
get())
這是因為當limit比capacity小時
上面的代碼將會拋出一個BufferUnderflowException異常
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26014.html