一、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 对象

java缓冲流复制文件 java io流 缓冲区_NIO

三、缓冲区

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;

java缓冲流复制文件 java io流 缓冲区_数据_02

4. Buffer的常用方法

java缓冲流复制文件 java io流 缓冲区_数据_03

java缓冲流复制文件 java io流 缓冲区_System_04

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());
}

输出结果:

java缓冲流复制文件 java io流 缓冲区_java缓冲流复制文件_05

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
}

输出结果:

java缓冲流复制文件 java io流 缓冲区_ci_06