java SE 1.4引入了大量用于改進輸入/輸出處理機制的特性,它們位于java.nio包中,合稱“新I/O”。
這個包中包含對下列特性的支持:字符集編碼器和解碼器,非阻塞的I/O ,內存映射文件,文件加鎖機制 。字符集編碼器和解碼器在前面已經說過了。
內存映射文件 大多數操作系統都可以利用虛擬內存實現來將一個文件或者文件的一部分“映射”到內存中。然后,這個文件就可以當作是內存數組一樣地訪問,這比傳統的文件操作要快得多 。內存映射比使用帶緩沖的順序輸入要稍微快一點,但是比使用RandomaccessFile快很多。當然,精確的值因機器不同會產生很大的差異,但是很明顯,如果需要使用隨機訪問,那么性能受損是不可避免的。另一方面,對于中等尺寸文件的順序讀入沒有必要使用內存映射。首先,從文件中獲得一個通道( channel),通道是用于磁盤文件的一種抽象,它使我們可以訪問諸如內存映射、文件加鎖機制以及文件間快速數據傳遞等操作系統特性。我們可以通過調用getChannel方法來獲得通道,這個方法已經添加到了FileInputStream、FileOutputStream和RandomAccessFile類中。
FileInputStream f = new FileInputStream(xxx);FileChannel chnanel = f.getChannel();然后,通過調用FileChannel類的map方法從這個通道中獲得一個MappedByteBuffer。你可以指定想要映射的文件區域與映射模式,有三種模式可以得到支持:
FileChannel.MapMode.READ_ONLY:所產生的緩沖區是只讀的,任何對該緩沖區寫入的嘗試都會導致ReadOnlyBufferException異常。FileChannel.MapMode.READ_WRITE:所產生的緩沖區是可寫的,任何修改都會在某個時刻寫回到文件中。注意,其他映射同一個文件的程序可能不能立即看到這些修改,多個程序同時進行文件映射的確切行為是依賴于操作系統的。
FileChannel.MapMode.PRIVATE:所產生的緩沖區是可寫的,但是任何修改對這個緩沖區來說都是私有的,不會傳播到文件中。一旦有了緩沖區,就可以使用ByteBuffer類和Buffer超類的方法讀寫數據了。
文件加鎖機制
文件鎖可以控制對文件或文件中某個范圍的字節的訪問,但是,文件加鎖機制在不同的操作系統之間變化很大。
FileChannelFileLock lock()在整個文件上獲得一個獨占的鎖,這個方法將阻塞直至獲得鎖。FileLock tryLock()在整個文件上獲得一個獨占的鎖,或者在無法獲得鎖的情況下返回null。FileLock lock(long position, long size, boolean shared)FileLock tryLock(long position, long size, boolean shared)在文件的一個區域上獲得鎖。第一個方法將阻塞直至獲得鎖,而第二個方法將在無法獲得鎖時返回null。參數: position 要鎖定區域的起始位置size 要鎖定區域的尺寸shared true為共享鎖, false為獨占鎖FileLockvoid release()釋放這個鎖。MappedByteBuffer map(FileChannel.MapMode mode, long position, long size)將文件的一個區域映射到內存中。參數: mode FileChannel.MapMode類中的常量READ_ONLY、 READ_WRITE、或PRIVATE之一position 映射區域的起始位置size 映射區域的大小bufferboolean hasRemaining()如果當前的緩沖區位置沒有達到這個緩沖區的界限位置則返回true。int limit()返回這個緩沖區的界限位置,即沒有任何值可用的第一個位置。ByteBufferbyte get()從當前位置獲得一個字節,并將當前位置推到下一個字節。byte get(int index)從指定索引處獲得一個字節。ByteBuffer put(byte b)向當前位置推入一個字節,并將當前位置推到下一個字節。返回對這個緩沖區的引用。ByteBuffer put(int index, byte b)向指定索引處推入一個字節。返回對這個緩沖區的引用。ByteBuffer get(byte[] destination)ByteBuffer get(byte[] destination, int offset, int length)用緩沖區中的字節來填充字節數組,或者字節數組的某個區域,并將當前位置向前推讀入的字節數個位置。如果緩沖區不夠,那么就不會讀入任何字節,并拋出BufferUnderflowException。返回對這個緩沖區的引用。參數: destination 要填充的字節數組offset 要填充區域的偏移量length 要填充區域的長度ByteBuffer put(byte[] source)ByteBuffer put(byte[] source, int offset, int length)將字節數組中的所有字節或者給定區域的字節都推入緩沖區中,并將當前位置向前推寫出的字節數個位置。如果緩沖區不夠,那么就不會讀入任何字節,并拋出BufferUnderflow Exception。返回對這個緩沖區的引用。參數: source 要寫出的數組offset 要寫出區域的偏移量length 要寫出區域的長度Xxx getXxx()Xxx getXxx(int index)ByteBuffer putXxx(xxx value)ByteBuffer putXxx(int index, xxx value)獲得或放置一個二進制數。 Xxx Int、 Long、 Short、 Char、 Float或Double中的一個。ByteBuffer order(ByteOrder order)ByteOrder order()設置或獲得字節順序, order的值是ByteOrder類的常量BIG_ENDIAN或LITTLE_ENDIAN中的一個Buffer clear()通過將位置復位到0,并將界限復位到容量,使這個緩沖區為寫出做好準備。返回this。Buffer flip()通過將界限設置到位置,并將位置復位到0,使這個緩沖區為讀入做好準備。返回this。Buffer rewind()通過將讀寫位置復位到0,并保持極限不變,使這個緩沖區為重新讀入相同的值做好準備。返回this。Buffer mark()將這個緩沖區的標記設置到讀寫位置,返回this。Buffer reset()將這個緩沖區的位置設置到標記,從而允許被標記的部分可以再次被讀入或寫出,返回this。int remaining()返回剩余可讀入或可寫出的值的數量,即界限與位置之間的差異。int position()返回這個緩沖區的位置。int capacity()返回這個緩沖區的容量。charbufferchar get()CharBuffer get(char[] destination)CharBuffer get(char[] destination, int offset, int length)從這個緩沖區的位置處開始,獲得一個char值,或者某個范圍的char值,然后將位置向前推過所讀入的字符。最后兩個方法返回this。CharBuffer put(char c)CharBuffer put(char[] source)CharBuffer put(char[] source, int offset, int length)CharBuffer put(String source)CharBuffer put(CharBuffer source)從這個緩沖區的位置處開始,推入一個char值,或者某個范圍的char值,然后將位置向前推過所寫出的字符。CharBuffer read(CharBuffer destination)從這個緩沖區中獲得char值,然后將它們推入目標緩沖區,直至達到目標緩沖區的界限。返回this。
新聞熱點
疑難解答