Java NIO Buffer

Java NIO中的Buffer用於和NIO通道進行交互。如你所知,數據是從通道讀入緩衝區,從緩衝區寫入到通道中的。

緩衝區本質上是一塊可以寫入數據,然後可以從中讀取數據的內存。這塊內存被包裝成NIO Buffer對象,並提供了一組方法,用來方便的訪問該塊內存。

NIO中的關鍵Buffer實現有:ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer,分別對應基本數據類型: byte, char, double, float, int, long, short。當然NIO中還有MappedByteBuffer, HeapByteBuffer, DirectByteBuffer等這裏先不進行陳述。

首先我們先創建一個Buffer

 //create buffer with capacity of 11bytes
 ByteBuffer buf = ByteBuffer.allocate(11);

可以把Buffer簡單地理解爲一組基本數據類型的元素列表,它通過幾個變量來保存這個數據的當前位置狀態:

索引 說明
capacity 緩衝區數組的總長度
position 下一個要操作的數據元素的位置
limit 所有對Buffer讀寫操作都會以limit變量的值作爲上限。


我們通過ByteBuffer.allocate(11)方法創建了一個11個byte的數組的緩衝區,初始狀態如上圖,position的位置爲0,capacity和limit默認都是數組長度。當我們寫入5個字節時,變化如下圖:
這裏寫圖片描述
這時我們需要將緩衝區中的5個字節數據寫入Channel的通信信道,所以我們調用ByteBuffer.flip()方法,變化如下圖所示(position設回0,並將limit設成之前的position的值):
這裏寫圖片描述
這裏再次解釋一下limit:
在寫模式下,Buffer的limit表示你最多能往Buffer裏寫多少數據。
當切換Buffer到讀模式時, limit表示你最多能讀到多少數據。因此,當切換Buffer到讀模式時,limit會被設置成寫模式下的position值。

clear方法

    public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

clear將緩衝區清空,一般是在重新寫緩衝區時調用。

flip方法

    public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

首先將limit設置爲當前位置,然後將position設置爲 0。如果已定義了標記。 常與compact方法一起使用。通常情況下,在準備從緩衝區中讀取數據時調用flip方法。

compact()方法將所有未讀的數據拷貝到Buffer起始處。然後將position設到最後一個未讀元素正後面。limit屬性依然像clear()方法一樣,設置成capacity。現在Buffer準備好寫數據了,但是不會覆蓋未讀的數據。

hasRemaining

    public final boolean hasRemaining() {
        return position < limit;
    }
package com.hutonm.nio;

import org.junit.Before;
import org.junit.Test;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.RandomAccess;

public class Niotest {

    @Test
    public void method1(){
        RandomAccessFile aFile = null;

        try {
            aFile = new RandomAccessFile("src/nio.text","rw");
            FileChannel fileChannel = aFile.getChannel();

            //create buffer with capacity of 1024 bytes
            ByteBuffer buf = ByteBuffer.allocate(1024);
            //read into buffer
            int byteRead = fileChannel.read(buf);

            // print byteRead
            //System.out.println(byteRead);


            while (byteRead != -1){

                //make buffer read for read
                buf.flip();

                while (buf.hasRemaining()){
                    System.out.print((char)buf.get());
                }

                //清除已讀數據
                buf.compact();

                byteRead = fileChannel.read(buf);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

參考:
http://www.importnew.com/19816.html
http://ifeve.com/buffers/

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