1. 程式人生 > >NIO-1-Java NIO簡介&緩衝區

NIO-1-Java NIO簡介&緩衝區

一、NIO簡介

Java NIO(New IO)是從Java 1.4開始引入的一個新的IO API,可以代替標準的Java IO API。NIO以更加高效的方式進行檔案的讀寫操作。

NIO與IO的區別

IO NIO
面向流 面向快取區
阻塞IO(Blocking IO) 非阻塞IO
選擇器

二、通道與快取區

  • 通道(chanel)
    通道表示開啟到IO裝置(檔案、套接字)的連線。
  • 緩衝區(Buffer)
    一個特定基本資料型別的容器。由java nio包定義的緩衝區都是Buffer類的子類。
    Buffer主要與通道進行互動,資料從通道寫入緩衝區,資料從緩衝區中寫入通道。

static XxxBuffer allocate(int capacity) : 建立一個容量為capacity 的XxxBuffer 物件

這裡寫圖片描述

三、緩衝區

1.緩衝區 :

在 Java NIO 中負責資料的存取。緩衝區就是陣列。用於儲存不同資料型別的資料。
根據資料型別不同(boolean除外),提供了相應型別的緩衝區。
* ByteBuffer
* CharBuffer
* ShortBuffer
* IntBuffer
* LongBuffer
* FloatBuffer
* DoubleBuffer

上述緩衝區的管理方式幾乎一致,通過allocate()獲取緩衝區。

2. 緩衝區存取資料的兩個核心方法

  • put():存入資料到緩衝區中。
  • get():獲取緩衝區中的資料。

3.緩衝區中的4個核心屬性

  • 容量(capacity):表示Buffer最大資料容量,不能為負,建立後不能更改。
  • 限制(limit):第一個不應該讀取或寫入的資料索引,即位於limit後的資料不能讀寫。
  • 位置(position):寫一個要讀取或寫入的資料的索引。
  • 標記(mark)與重置(reset):標記一個指定的索引,之後再通過reset恢復到這個位置。

標記、位置、限制、容量遵守以下不變式:0<=mark<=position<=limit<=capacity

private int mark = -1;
private int position = 0;
private int limit;
private int capacity;

這裡寫圖片描述

4. Buffer的常用方法

這裡寫圖片描述

這裡寫圖片描述

public static void main(String[] args) {
    String str = "abcd3";

    //1. 分配一個指定大小的緩衝區。
    ByteBuffer buf = ByteBuffer.allocate(1024);

    System.out.println("-----------allocate--------");
    System.out.println("position:" + buf.position());
    System.out.println("limit:" + buf.limit());
    System.out.println("capacity:" + buf.capacity());

    //2.利用put方法存入資料到緩衝區中
    buf.put(str.getBytes());//position位置變成了5
    System.out.println("position:" + buf.position());//5

    System.out.println("-----------put--------");
    System.out.println("position:" + buf.position());
    System.out.println("limit:" + buf.limit());
    System.out.println("capacity:" + buf.capacity());

    //3. 呼叫flip()切換到讀資料模式
    buf.flip();
    System.out.println("-----------flip--------");
    System.out.println("position:" + buf.position());//0
    System.out.println("limit:" + buf.limit());//5
    System.out.println("capacity:" + buf.capacity());//1024

    //4. get()讀取緩衝區的資料
    byte[] dst = new byte[buf.limit()];
    buf.get(dst);
    System.out.println(new String(dst,0,dst.length));
    System.out.println("-----------get--------");
    System.out.println("position:" + buf.position());//5
    System.out.println("limit:" + buf.limit());//5
    System.out.println("capacity:" + buf.capacity());//1024

    // 5. rewind():可重複讀資料
    buf.rewind();
    System.out.println("-----------rewind--------");
    System.out.println("position:" + buf.position());//0
    System.out.println("limit:" + buf.limit());//5
    System.out.println("capacity:" + buf.capacity());//1024

    // 6. clear:清空緩衝區,但是緩衝區的資料依然存在,但是處於“被遺忘”狀態
    buf.clear();
    System.out.println("-----------clear--------");
    System.out.println("position:" + buf.position());
    System.out.println("limit:" + buf.limit());
    System.out.println("capacity:" + buf.capacity());
}

輸出結果:

這裡寫圖片描述

public void testMark() {
    String str = "abcde";

    ByteBuffer buf = ByteBuffer.allocate(1024);

    buf.put(str.getBytes());

    buf.flip();

    byte[] dst = new byte[buf.limit()];
    buf.get(dst, 0, 2);
    System.out.println(new String(dst,0,2));

    System.out.println("position:" + buf.position());//2

    //mark : 標記
    buf.mark();
    System.out.println("-----------remark--------");

    buf.get(dst,2,2);
    System.out.println("-----------get--------");
    System.out.println(new String(dst,2,2));
    System.out.println("position:" + buf.position());//4

    //reset:恢復到標記位置
    buf.reset();
    System.out.println("-----------reset--------");
    System.out.println("position:" + buf.position());//2
}

輸出結果:

這裡寫圖片描述