1.什么是NIO
NIO 是 java New IO 的简称,在 jdk1.4 里提供的新 API。
1. 为所有的原始类型提供 (Buffer) 缓存支持。
2. 字符集编码解码解决方案。
3. Channel:通道(一个新的原始 I/O 抽象)。
4. 支持锁和内存映射文件的文件访问接口。
5. 提供多路 (non-bloking) 非阻塞式的高伸缩性网络 I/O 。
NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。
2.IO与NIO的区别
IO | NIO |
面向Stream | 面向Buffer |
阻塞IO | 非阻塞IO |
Selectors |
3.NIO实现数据存取
从类图上可以看出都继承与Buffer类,在Buffer类中有四个重要属性:
下面就通过代码来理解Buffer的属性及方法:
package com.hmi.NIO;
import java.nio.ByteBuffer;
import org.junit.Test;
/**
* 一.缓冲区(Buffer):在java NIO中负责存取数据,底层是数组,用于存储不同数据类型的数据
*
* 根据数据类型的不同,有不同的缓冲区(Boolean除外):
* ByteBuffer
* ShortBuffer
* IntBuffer
* LongBuffer
* FloatBuffer
* DoubleBuffer
* CharBuffer
* 上述缓冲区都是通过allocate()获取缓冲区
*
* 二. 缓冲区存取数据的两个核心方法: put()向缓冲区存储数据 get()从缓冲区中取数据
*
* 三.缓冲区的核心属性:
* capacity:缓冲区存储数据的最大容量,一旦声明不能改变(底层为数组)。
* limit:缓冲区的界限,表示可以操控数据的大小,即limit后面的1数据不能进行读写。
* position:缓冲区正在操控数据的位置。
* mark:标记position,使用reset()方法后重新回到该位置。
* mark <= position <= limit <= capacity
*/
public class BufferTest {
@Test
public void Test1() {
// 分配一个指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
String str = "abcde";
// 1.调用put()方法,往缓冲区里存数据
buf.put(str.getBytes());
System.out.println("调用put()方法,往缓冲区存数据后:");
System.out.println("-------------------");
System.out.println("缓冲区当前的最大容量:" + buf.capacity());
System.out.println("缓冲区当前的最大界限:" + buf.limit());
System.out.println("缓冲区当前的操作位置:" + buf.position());
System.out.println("-------------------");
// 2.调用flip()方法,切换为读数据模式
buf.flip();
System.out.println("调用flip()方法,切换为读数据模式后:");
System.out.println("-------------------");
System.out.println("缓冲区当前的最大容量:" + buf.capacity());
System.out.println("缓冲区当前的最大界限:" + buf.limit());
System.out.println("缓冲区当前的操作位置:" + buf.position());
System.out.println("-------------------");
// 3.调用get()方法,读取缓冲区数据
byte[] dst = new byte[buf.limit()];
buf.get(dst);
System.out.println("调用get()方法,读取缓冲区数据后:");
System.out.println("缓冲区里的数据为:" + new String(dst, 0, dst.length));
System.out.println("-------------------");
System.out.println("缓冲区当前的最大容量:" + buf.capacity());
System.out.println("缓冲区当前的最大界限:" + buf.limit());
System.out.println("缓冲区当前的操作位置:" + buf.position());
System.out.println("-------------------");
// 4.调用clear()方法,清空缓冲区,但缓冲区里的数据任然存在,处于"被遗忘"状态
buf.clear();
System.out.println("调用clear()方法,清空缓冲区后:");
System.out.println("缓冲区里的数据为:" + new String(dst, 0, dst.length));
System.out.println("-------------------");
System.out.println("缓冲区当前的最大容量:" + buf.capacity());
System.out.println("缓冲区当前的最大界限:" + buf.limit());
System.out.println("缓冲区当前的操作位置:" + buf.position());
System.out.println("-------------------");
}
@Test
public void Test2() {
// 1.分配一个指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
String str = "abcde";
// 2.往缓冲区中添加数据
buf.put(str.getBytes());
// 3.切换为读取数据模式
buf.flip();
// 定义字节数组存放数据
byte[] dst = new byte[buf.limit()];
// 取前两位数据,并转换为字符串输出
buf.get(dst, 0, 2);
System.out.println("缓冲区前两位的数据为:" + new String(dst, 0, 2));
System.out.println("缓冲区当前的操作位置:" + buf.position());
// 4.标记当前position
buf.mark();
// 取后三位数据,并转换为字符串输出
buf.get(dst, 2, 3);
System.out.println("缓冲区后三位的数据为:" + new String(dst, 2, 3));
System.out.println("缓冲区当前的操作位置:" + buf.position());
// 5,使用reset(),重置position为标记位置
buf.reset();
System.out.println("经过reset()后,缓冲区的操作位置:" + buf.position());
}
}
Test1()运行结果:
Test2()运行结果: