1. 程式人生 > >Java NIO——Buffer

Java NIO——Buffer

文章目錄


轉載自 併發程式設計網 – ifeve.com本文連結地址: Java NIO系列教程(三) Buffer

1 概述

    Buffer,即緩衝區,主要用於與NIO通道進行互動。資料從Channel讀取Buffer,從Buffer寫入Channel。
    緩衝區本質上是一塊可以寫入資料,然後可以從中讀取資料的記憶體。這塊記憶體被包裝成NIO Buffer物件,並提供了一組方法,用來方便的訪問該塊記憶體。
Buffer型別

ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer

2 基本屬性

capacity
    快取區的容量,不可改變。只能往裡寫capacity個byte、int,char等型別。
position
    當你要寫資料到Buffer中時,position表示當前可寫的位置。初始的position值為0(也可以用過方法進行改變)。當一個byte、int等資料寫到Buffer後, position會向前移動到下一個可插入資料的Buffer單元。position最大可為capacity – 1.
    當讀取資料時,也是從某個特定位置讀。當從Buffer的position處讀取資料完成時,position向前移動到下一個可讀的位置。
limit


    在寫資料時,Buffer的limit表示你最多能往Buffer裡寫多少資料,position移動到limit寫操作停止。初始limit的值等於Buffer的capacity。
    當讀取資料時, limit表示你最多能讀到多少資料,position移動到limit讀操作停止。
無論在讀資料時還是在寫資料時,只要position超過了limit就會丟擲異常。

3 基本用法

使用Buffer讀寫資料一般遵循以下幾個步驟:

  • 1 採用allocate分配一塊固定容量的緩衝區。
  • 2 寫入資料到Buffer
  • 3 呼叫flip()方法,從寫模式切換到讀模式
  • 4 從Buffer中讀取資料
  • 5 呼叫clear()方法或者compact()方法,清空緩衝區資料

3.1 DEMO

String src =  "bufferTest1.txt";
        RandomAccessFile r=null;
        try {
            r = new RandomAccessFile(src,"rw");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        FileChannel channel = r.getChannel();
        // 1. 建立一塊大小為8的緩衝區
        ByteBuffer buffer = ByteBuffer.allocate(8);
        int len =0;
        //2. 讀入資料到buffer
        while ((len= channel.read(buffer))!=-1){
            //3 切換到讀取模式
            buffer.flip();
            while (buffer.hasRemaining()){
                // 4 每次讀取一個位元組
                byte byte1= buffer.get();
                System.out.println(byte1);
            }
            // 5 清空buffer
            buffer.clear();
        }
        r.close();

3.2 獲取buffer

通過allocate()方法分配一個固定容量的buffer

ByteBuffer b = ByteBuffer.allocate(8);

3.3 讀取資料到Buffer

寫資料到Buffer有兩種方式:

  • 從Channel寫到Buffer。
  • 通過Buffer的put()方法寫到Buffer裡。
channel.read(buffer))
buffer.put(some thing);//byte,byte[],buffer等

3.4 flip()

    flip方法將Buffer從寫模式切換到讀模式。呼叫flip()方法會將position設回0,並將limit設定成之前position的值。
換句話說,position現在用於標記讀的位置,limit表示之前寫進了多少個byte、char等 —— 現在能讀取多少個byte、char等。

3.5 clear()與compact()

    一旦讀完Buffer中的資料,需要讓Buffer準備好再次被寫入。可以通過clear()或compact()方法來完成。
    如果呼叫的是clear()方法,position將被設回0,limit被設定成 capacity的值。換句話說,Buffer 被清空了。Buffer中的資料並未清除,只是這些標記告訴我們可以從哪裡開始往Buffer裡寫資料。
    如果Buffer中有一些未讀的資料,呼叫clear()方法,資料將“被遺忘”,意味著不再有任何標記會告訴你哪些資料被讀過,哪些還沒有。
    如果Buffer中仍有未讀的資料,且後續還需要這些資料,但是此時想要先先寫些資料,那麼使用compact()方法。
   &160;compact()方法將所有未讀的資料拷貝到Buffer起始處。然後將position設到最後一個未讀元素正後面。limit屬性依然像clear()方法一樣,設定成capacity。現在Buffer準備好寫資料了,但是不會覆蓋未讀的資料。

3.6mark()與reset()方法

   &160;通過呼叫Buffer.mark()方法,可以標記Buffer中的一個特定position。之後可以通過呼叫Buffer.reset()方法恢復到這個position。例如:

buffer.mark();
//call buffer.get() a couple of times, e.g. during parsing.
buffer.reset();  //set position back to mark.