一、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
}
输出结果: