ByteBuffer
在Buffer的子類(lèi)中,ByteBuffer是一個(gè)地位較為特殊的類(lèi),因為在java.io.channels中定義的各種channel的IO操作基本上都是圍繞ByteBuffer展開(kāi)的。
ByteBuffer定義了4個(gè)static方法來(lái)做創(chuàng )建工作:
ByteBuffer allocate(int capacity)
創(chuàng )建一個(gè)指定capacity的ByteBuffer。
ByteBuffer allocateDirect(int capacity)
創(chuàng )建一個(gè)direct的ByteBuffer,這樣的ByteBuffer在參與IO操作時(shí)性能會(huì )更好(很有可能是在底層的實(shí)現使用了DMA技術(shù)),相應的,創(chuàng )建和回收direct的ByteBuffer的代價(jià)也會(huì )高一些。isDirect()方法可以檢查一個(gè)buffer是否是direct的。
ByteBuffer wrap(byte [] array)
ByteBuffer wrap(byte [] array, int offset, int length)
把一個(gè)byte數組或byte數組的一部分包裝成ByteBuffer。
ByteBuffer定義了一系列g(shù)et和put操作來(lái)從中讀寫(xiě)byte數據,如下面幾個(gè):
byte get()
ByteBuffer get(byte [] dst)
byte get(int index)
ByteBuffer put(byte b)
ByteBuffer put(byte [] src)
ByteBuffer put(int index, byte b)
這些操作可分為絕對定位和相對定為兩種,相對定位的讀寫(xiě)操作依靠position來(lái)定位Buffer中的位置,并在操作完成后會(huì )更新position的值。
在其它類(lèi)型的buffer中,也定義了相同的函數來(lái)讀寫(xiě)數據,唯一不同的就是一些參數和返回值的類(lèi)型。
除了讀寫(xiě)byte類(lèi)型數據的函數,ByteBuffer的一個(gè)特別之處是它還定義了讀寫(xiě)其它primitive數據的方法,如:
int getInt()
從ByteBuffer中讀出一個(gè)int值。
ByteBuffer putInt(int value)
寫(xiě)入一個(gè)int值到ByteBuffer中。
讀寫(xiě)其它類(lèi)型的數據牽涉到字節序問(wèn)題,ByteBuffer會(huì )按其字節序(大字節序或小字節序)寫(xiě)入或讀出一個(gè)其它類(lèi)型的數據(int,long…)。字節序可以用order方法來(lái)取得和設置:
ByteOrder order()
返回ByteBuffer的字節序。
ByteBuffer order(ByteOrder bo)
設置ByteBuffer的字節序。
ByteBuffer另一個(gè)特別的地方是可以在它的基礎上得到其它類(lèi)型的buffer。如:
CharBuffer asCharBuffer()
為當前的ByteBuffer創(chuàng )建一個(gè)CharBuffer的視圖。在該視圖buffer中的讀寫(xiě)操作會(huì )按照ByteBuffer的字節序作用到ByteBuffer中的數據上。
用這類(lèi)方法創(chuàng )建出來(lái)的buffer會(huì )從ByteBuffer的position位置開(kāi)始到limit位置結束,可以看作是這段數據的視圖。視圖buffer的readOnly屬性和direct屬性與ByteBuffer的一致,而且也只有通過(guò)這種方法,才可以得到其他數據類(lèi)型的direct buffer。
ByteOrder
用來(lái)表示ByteBuffer字節序的類(lèi),可將其看成java中的enum類(lèi)型。主要定義了下面幾個(gè)static方法和屬性:
ByteOrder BIG_ENDIAN
代表大字節序的ByteOrder。
ByteOrder LITTLE_ENDIAN
代表小字節序的ByteOrder。
ByteOrder nativeOrder()
返回當前硬件平臺的字節序。
MappedByteBuffer
ByteBuffer的子類(lèi),是文件內容在內存中的映射。這個(gè)類(lèi)的實(shí)例需要通過(guò)FileChannel的map()方法來(lái)創(chuàng )建。
接下來(lái)看看一個(gè)使用ByteBuffer的例子,這個(gè)例子從標準輸入不停地讀入字符,當讀滿(mǎn)一行后,將收集的字符寫(xiě)到標準輸出:
public static void main(String [] args) throws IOException {
// 創(chuàng )建一個(gè)capacity為256的ByteBuffer
ByteBuffer buf = ByteBuffer.allocate(256);
while (true) {
// 從標準輸入流讀入一個(gè)字符
int c = System.in.read();
// 當讀到輸入流結束時(shí),退出循環(huán)
if (c == -1)
break;
// 把讀入的字符寫(xiě)入ByteBuffer中
buf.put((byte) c);
// 當讀完一行時(shí),輸出收集的字符
if (c == '\n') {
// 調用flip()使limit變?yōu)楫斍暗膒osition的值,position變?yōu)?,
// 為接下來(lái)從ByteBuffer讀取做準備
buf.flip();
// 構建一個(gè)byte數組
byte [] content = new byte[buf.limit()];
// 從ByteBuffer中讀取數據到byte數組中
buf.get(content);
// 把byte數組的內容寫(xiě)到標準輸出
System.out.print(new String(content));
// 調用clear()使position變?yōu)?,limit變?yōu)閏apacity的值,
// 為接下來(lái)寫(xiě)入數據到ByteBuffer中做準備
buf.clear();
}
}
}