JAVA NIO系列(三) Buffer 解讀


緩沖區分類 

NIO中的buffer用於和通道交互,數據是從通道讀入緩沖區,從緩沖區中寫入通道的。Buffer就像一個數組,可以保存多個類型相同的數據。每種基本數據類型都有對應的Buffer類:

緩沖區的屬性

1、capacity(容量):buffer本質是一個數組,在初始化時有固定的大小,這個值就是容量。容量不可改變,一旦緩沖區滿了,需要將其清空才能將繼續進行讀寫操作。

2、position(位置):表示當前的位置,初始化時為0,當一個基本數據類型的數據寫入buffer時,position會向前移動到下一個可插入數據的Buffer單元。position最大值可以是                              capacity-1。

3、limit(限制):在緩沖區寫模式下,limit表示你最多能往Buffer里寫多少數據,大小等於capacity;在緩沖區讀模式下,limit表示能從緩沖區內讀取到多少數據,因此,當切          換Buffer到讀模式時,limit會被設置成寫模式下的position值。

                          

一、使用NIO進行文件內容的復制:

public class BufferTest
{
    public static void main(String[] args) throws Exception
    {
        FileInputStream fis = new FileInputStream("d:/in.txt");
        FileChannel channel = fis.getChannel();
        
        FileOutputStream fos = new FileOutputStream("d:/out.txt");
        FileChannel channel1 = fos.getChannel();
        //初始化緩沖區
        ByteBuffer buffer = ByteBuffer.allocate(20);
        System.out.println("通道文件的大小:" + channel.size());
        System.out.println("緩沖區初始化時當前位置:" + buffer.position());
        System.out.println("緩沖區初始化時可寫的限制:" + buffer.limit());
        System.out.println("---------循環開始-----");
        //判斷通道內數據是否讀取完成
        while(-1 != channel.read(buffer))
        {
            System.out.println("緩沖區寫模式下當前位置:" + buffer.position());
            System.out.println("緩沖區寫模式下的限制:" + buffer.limit());
            //將緩沖區從寫模式切換到讀模式
            buffer.flip();
            System.out.println("緩沖區讀模式下當前位置:" + buffer.position());
            System.out.println("緩沖區讀模式下的限制:" + buffer.limit());
            //判斷緩沖區內是否還有數據可讀取
            while(buffer.hasRemaining())
            {
                channel1.write(buffer);
            }
            buffer.clear();
        }
        channel.close();
        channel1.close();
        fis.close();
    }
}

執行結果:

通道文件的大小:36
緩沖區初始化時當前位置:0
緩沖區初始化時可寫的限制:20
---------循環開始-----
緩沖區寫模式下當前位置:20
緩沖區寫模式下的限制:20
緩沖區讀模式下當前位置:0
緩沖區讀模式下的限制:20
緩沖區寫模式下當前位置:16
緩沖區寫模式下的限制:20
緩沖區讀模式下當前位置:0
緩沖區讀模式下的限制:16

1、文件的大小為36個字節,緩沖區初始化的大小為20個字節,程序中進行了兩次讀取操作,才完成了文件內容的復制。

2、可以看到,在緩沖區寫模式下,limit的大小始終等於capacity;而在讀模式下,limit等於模式切換前position的大小。

二、Buffer的分配

Buffer對象的獲取需要進行分配,每種類型的Buffer對象都有一個allocate方法。我們以程序中的ByteBuffer對象為例:

ByteBuffer buffer = ByteBuffer.allocate(20);

我們去跟蹤下源碼:

1  public static ByteBuffer allocate(int capacity) {
2     if (capacity < 0)
3         throw new IllegalArgumentException();
4     return new HeapByteBuffer(capacity, capacity);
5     }
HeapByteBuffer(int cap, int lim) {        // package-private

    super(-1, 0, lim, cap, new byte[cap], 0);

//在這里已經創建一個以cap為大小的字節數組(new byte[cap])

ByteBuffer(int mark, int pos, int lim, int cap,    // package-private
         byte[] hb, int offset)
    {
    super(mark, pos, lim, cap);
    this.hb = hb;
    this.offset = offset;
    }
Buffer(int mark, int pos, int lim, int cap) {    // package-private
    if (cap < 0)
        throw new IllegalArgumentException();
    this.capacity = cap;
    limit(lim);
    position(pos);
    if (mark >= 0) {
        if (mark > pos)
        throw new IllegalArgumentException();
        this.mark = mark;
    }
    }

//數組的創建在ByteBuffer類里面已經創建,在父類Buffer里,初始化容量、限制、位置等一些公共屬性。

三、Buffer模式的切換

buffer.flip()該方法是用於將緩沖區從寫模式切換到讀模式,這是一種固定寫法,該方法的源碼如下:

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

 調用flip()方法會將position設回0,並將limit設置成之前position的值。

四、remaind方法

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

將position的位置設置為0,表示可以重新讀取Buffer中的所有數據,limit保持不變。

五、clear方法

1  public final Buffer clear() {
2     position = 0;
3     limit = capacity;
4     mark = -1;
5     return this;

1、一旦完成對buffer中數據的讀取,需要讓buffer做好再次被寫入的准備,這時候可以調用clear方法來完成。

2、clear方法將position設置為0,limit設置為容量的值,也就意味着buffer被清空了,但是這個清空的概念是寫入數據可以從緩沖區的指定位置開始,但buffer里面的數據並沒有        刪除。

3、如果buffer里面還有數據沒有被讀取,這個時候調用clear方法會導致那些數據被“遺忘”,因為沒有標記告訴你哪些是讀取過哪些沒有被讀取。

六、向buffer中寫入數據

1、通過channel寫入;

2、通過buffer的put方法寫入:

buffer.put("channel".getBytes());

七、從buffer中讀取數據

1、通過channel讀取;

2、通過buffer的get方法讀取:

byte b = buffer.get();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM