java編程思想讀書筆記 第十八章 java I/O系統(第四篇 新I/O)

新的I/O

JDK1.4的java.nio.*包中引入了新的javaI/O類庫,其目的在於提高速度,舊的I/O包已經使用nio重新實現過,以便充分利用這種速度提高。因此,即便我們不顯示的使用nio編寫代碼。也能從中受益。速度的提高在於所使用的結構更接近與操作系統執行的I/O方式:通道和緩衝器
ByteBuffer是唯一直接與通道交互的緩衝器,可以存儲未加工字節的緩存器;java.nio.ByteBuffer是相當基礎的類,通過告知分配多少存儲空間來創建一個ByteBuffer對象,並且還有一個方法選擇集,用於以原始的字節形式或基本數據類型輸出和讀取數據。沒辦法輸出或讀取對象;通過告知分配多少存儲空間來創建一個ByteBuffer對象。
舊I/O類庫中有三個類被修改了,用以產生FileChannel。這三個被修改的類是FileInputStream、FileOutputStream以及用於既讀又寫的RandomAccessFile。注意這些事字節操作流。Reader和Writer這種字符模式類不能用於產生通道,但是java.nio.Channels提供了實用方法,用以在通道中產生Reader和Writer。
下面的例子使用了上面三種類型的流,用以產生可寫的、可讀可寫的及可讀的通道。例子如下:

public class GetChannel {

    private static final int BSIZE = 1024;
    public static void main(String[] args) throws Exception{
        FileChannel fChannel = new FileOutputStream("").getChannel();
        fChannel.write(ByteBuffer.wrap("".getBytes()));
        fChannel.close();
        fChannel = new RandomAccessFile("文件名字", "rw").getChannel();
        fChannel.position(fChannel.size());
        fChannel.write(ByteBuffer.wrap("文件名字".getBytes()));
        fChannel.close();
        fChannel = new FileInputStream("文件名字").getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
        fChannel.read(buffer);
        buffer.flip();
        while (buffer.hasRemaining()) {
            System.out.println((char)buffer.get());
        }

    }
}

對於這裏展示的任何流,getChannel()將會產生一個FileChannel。可以向它傳送用於讀寫的ByteBuffer,並且可以鎖定文件的某些區域用於獨佔式訪問。
將字節存放於ByteBuffered的方法:
1)使用一種“put”方法直接對它們進行填充,填入一個或多個字節,或基本數據類型的值。
2)也可以使用warp()方法將已存在的字節數組“包裝”到ByteBuffer中。一旦如此,就不再複製底層的數組,而是把它作爲所產生的ByteBuffer的存儲器。我們稱之爲數組支持的ByteBuffer。
對於只讀訪問,必須顯示的使用靜態的allocate()方法分配ByteBuffer。allocateDirect()是更高的速度,但是由於它依賴於平臺,隨着平臺不同而不同,故需要謹慎使用。
一旦調用FileChaal.read(ByteBuffer)來告知FileChannal向ByteBuffer存儲字節,就必須使用緩衝器上的flip();如果我們打算使用緩衝器執行進一步的read()操作,必須調用clear()來爲每個read()做好準備
1)flip():反轉此緩衝區,將限制設置爲當前位置,然後將位置設置爲0
2)rewind():返回到數據開始部分,與flip()不同,不會修改限制位置。
3)FileChannal.read():返回-1表示我們已經到達了輸入的末尾。
4)flip()是準備緩存器,以便他的信息可以由write()提取。write()操作之後,信息仍在緩衝器中,接着clear()操作則對所有的內部指針重新安排,以便緩衝器在另一個read()操作期間能夠做好接收數據的準備。

1. 轉換數據
緩衝器容納的是普通的字節,爲了把它們轉換成字符,要麼在輸入的時候對其進行編碼,要麼在將其從緩衝器輸出時對它們進行編碼。可以使用java.nio.Charset類實現這些功能,該類提供了把數據編碼成多種不同類型的字符集的工具。

2. 獲取基本類型
儘管ByteBuffer只能保存字節類型的數據,但是它具有可以從其所容納的字節中產生出各種不同的基本類型值的方法。
向ByteBuffer插入基本類型數據的簡單方法使:利用acCharBuffer()、asShortBuffer()等獲得該緩衝上的視圖,然後使用視圖的put()方法。此方法適用於所有的基本類型,僅有一個小小的例外,即使用ShortBuffer的put()方法時,需要進行類型轉換,而其他所有的視圖緩衝器使用put()方法時,不需要進行類型轉換。

3. 視圖緩衝器
視圖緩衝器可以讓我們通過某個特定的基本數據類型的視窗查看其底層的ByteBuffer。ByteBuffer依然是實際存儲數據的地方,“支持”着前面的視圖,因此,對視圖的任何修改都會映射成爲對ByteBuffer中數據的修改。
一旦底層的ByteBuffer通過視圖緩衝器填滿了整數或其他基本類型時,就可以直接被寫到通道中了。正向向從通道中讀取那樣容易,然後使用視圖緩衝器可以把任何數據都轉化成某一特定的基本類型。

4. 用緩衝器操縱數據
如果想把一個字節數組寫到文件中去,那麼就應該使用ByteBuffer.wrap()方法把字節數組包裝起來,然後用getChannel()方法在FileOutputStream上打開一個通道,接着將來自於ByteBuffer的數據寫到FileChannel中。注意:ByteBuffer是將數據移進移出通道的唯一方式,並且只能創建一個獨立的基本類型緩衝器,或者使用“as”方法從ByteBuffer中獲得。也就是說,我們不能把基本類型的緩衝器轉換成ByteBuffer。然後,由於可以由視圖緩衝器將基本類型數據移進移出ByteBuffer,所以這也不是什麼真正的限制了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章