在NIO中,我們處理I/O操作的通道和緩沖區(qū)。
像流一樣的通道表示數(shù)據(jù)源/接收器和用于數(shù)據(jù)傳輸?shù)腏ava程序之間的連接。
通道提供雙向數(shù)據(jù)傳輸設(shè)施。我們可以使用通道來讀取數(shù)據(jù)以及寫入數(shù)據(jù)。根據(jù)我們的需要,我們可以獲得只讀通道,只寫通道或讀寫通道。
在基于流的I/O中,數(shù)據(jù)傳輸?shù)幕締挝皇且粋€(gè)字節(jié)。在基于通道的NIO中,數(shù)據(jù)傳輸?shù)幕締挝皇蔷彌_器。
緩沖區(qū)具有確定其可以包含的數(shù)據(jù)的上限的固定容量。
在基于通道的I/O中,我們將數(shù)據(jù)寫入緩沖區(qū),并將該緩沖區(qū)傳遞到寫入數(shù)據(jù)的通道。
為了從數(shù)據(jù)源讀取數(shù)據(jù),我們向一個(gè)通道傳遞一個(gè)緩沖區(qū)。通道將數(shù)據(jù)從數(shù)據(jù)源讀入緩沖區(qū)。
緩沖區(qū)是固定長(zhǎng)度的數(shù)據(jù)容器。有一個(gè)單獨(dú)的緩沖區(qū)類型來保存每種類型的基本值的數(shù)據(jù),除了布爾類型值。
緩沖區(qū)是我們程序中的一個(gè)對(duì)象。我們有一個(gè)單獨(dú)的類來表示每種類型的緩沖區(qū)。
所有緩沖區(qū)類都繼承自一個(gè)抽象的Buffer類。包含原始值的緩沖區(qū)類如下:
不同的緩沖區(qū)保存不同數(shù)據(jù)類型的數(shù)據(jù)。例如,ByteBuffer保存字節(jié)值; ShortBuffer保存短值;一個(gè)CharBuffer保存字符,等等。
以下是緩沖區(qū)的四個(gè)重要屬性。
緩沖區(qū)的容量是它可以容納的元素的最大數(shù)量。并且當(dāng)創(chuàng)建緩沖器時(shí)它是固定的。
我們可以通過調(diào)用hasArray()方法檢查緩沖區(qū)是否由數(shù)組支持,如果緩沖區(qū)由數(shù)組支持則返回true。
我們可以通過使用緩沖對(duì)象的array()方法來訪問支持?jǐn)?shù)組。
一旦我們?cè)L問了后臺(tái)數(shù)組,對(duì)該數(shù)組所做的任何更改都將反映在緩沖區(qū)中。
緩沖區(qū)具有返回其容量的capacity()方法。
我們可以使用特定緩沖區(qū)類的allocate()工廠方法創(chuàng)建一個(gè)緩沖區(qū),如下所示:
以下代碼創(chuàng)建一個(gè)容量為8的字節(jié)緩沖區(qū)
ByteBuffer bb = ByteBuffer.allocate(8);
獲得容量
int capacity = bb.capacity();
以下代碼創(chuàng)建一個(gè)容量為1024的字符緩沖區(qū)
CharBuffer cb = CharBuffer.allocate(1024);
字節(jié)緩沖區(qū)有一個(gè)名為allocateDirect()的方法,它創(chuàng)建一個(gè)字節(jié)緩沖區(qū),從操作系統(tǒng)內(nèi)存中分配內(nèi)存,而不是從JVM堆中分配內(nèi)存。
我們可以使用ByteBuffer類的isDirect()方法來檢查緩沖區(qū)是直接還是非直接。
// Create a direct byte buffer of 512 bytes capacity ByteBuffer bbd = ByteBuffer.allocateDirect(512);
另一種創(chuàng)建緩沖區(qū)的方法是使用緩沖區(qū)的static wrap()方法包裝數(shù)組。
byte[] byteArray = new byte[512]; ByteBuffer bb = ByteBuffer.wrap(byteArray);
我們可以使用相同的技術(shù)來創(chuàng)建緩沖區(qū)來存儲(chǔ)其他原始值。
當(dāng)我們創(chuàng)建一個(gè)緩沖區(qū)時(shí),緩沖區(qū)的所有元素都被初始化為零值。
緩沖區(qū)的每個(gè)元素都有一個(gè)索引。第一個(gè)元素的索引為0,最后一個(gè)元素的索引為capacity-1。
創(chuàng)建緩沖區(qū)時(shí),其位置設(shè)置為0,其限制等于其容量。
我們可以使用它的重載position()方法獲取/設(shè)置緩沖區(qū)的位置。
position()方法返回緩沖區(qū)位置的當(dāng)前值。
position(int newPosition)方法將緩沖區(qū)的位置設(shè)置為指定的newPosition值,并返回緩沖區(qū)的引用。
我們可以使用它的重載limit()方法獲取/設(shè)置緩沖區(qū)的限制。
limit()方法返回緩沖區(qū)限制的當(dāng)前值。limit(int newLimit)方法將緩沖區(qū)的限制設(shè)置為指定的newLimit值,并返回緩沖區(qū)的引用。
我們可以使用mark()方法為緩沖區(qū)的位置添加書簽。當(dāng)我們調(diào)用mark()方法時(shí),緩沖區(qū)將其位置的當(dāng)前值存儲(chǔ)為其標(biāo)記值。我們可以通過使用reset()方法將緩沖區(qū)的位置設(shè)置為之前加書簽的值。
緩沖區(qū)的標(biāo)記在創(chuàng)建時(shí)未定義。只有當(dāng)定義了它的標(biāo)記時(shí),我們才必須在緩沖區(qū)上調(diào)用reset()方法。否則,reset()方法會(huì)拋出InvalidMarkException異常。
以下代碼創(chuàng)建一個(gè)新緩沖區(qū)并顯示其四個(gè)屬性。
import java.nio.ByteBuffer; import java.nio.InvalidMarkException; public class Main { public static void main(String[] args) { ByteBuffer bb = ByteBuffer.allocate(8); System.out.println("Capacity: " + bb.capacity()); System.out.println("Limit: " + bb.limit()); System.out.println("Position: " + bb.position()); // The mark is not set for a new buffer. Calling the // reset() method throws a runtime exception if the mark is not set. try { bb.reset(); System.out.println("Mark: " + bb.position()); } catch (InvalidMarkException e) { System.out.println("Mark is not set"); } } }
上面的代碼生成以下結(jié)果。
更多建議: