一、NIO简介
java.nio全称Java non-blocking IO或Java New IO,是从jdk1.4 开始引入的一套新的IO api(New IO) ,为所有的原始类型(boolean类型除外)提供缓存支持的数据容器,使用它可以提供非阻塞式的高伸缩性网络。
NIO 和 IO的区别
面向缓冲区 面向流
非阻塞IO 阻塞IO(读的时候不能进行其他操作) 类似于ServerSocket中的accept() 阻塞式
选择器 无
二、NIO核心组成部分
Buffer:缓冲区
Buffer中有三个方法,capacity() limit() position() 返回结果都是int 他们始终遵循capacity() >= limit() > position()
Channel:通道
Selector:选择器(轮询器)
1、创建FileChannel
//第一种 inputStream和outputStream也都可以创建FIleChannel实例
RandomAccessFile aFile = new RandomAccessFile("文件地址, "rw");
FileChannel inChannel = aFile.getChannel();
//第二种 jdk1.7之后才能使用
FileChannel inChannel = FileChannel.open(Paths.get("文件地址"),StandardOpenOption.READ);
2、从FileChannel中读取数据
调用多个read()方法之一从FileChannel中读取数据
3、向FileChannel中写入数据
调用多个write()方法之一从FileChannel中写数据
三、使用FileChannel和ByteBuffer复制图片
直接缓冲区的使用,可以提高读写的速度。但是直接缓冲区的创建和销毁的开销比较大,一般大文件操作或能显著提高读写性能时使用。
//获取读通道
FileChannel fr = FileChannel.open(Paths.get("E:\\动漫.png"), StandardOpenOption.READ);
//获取写通道
FileChannel fw = FileChannel.open(Paths.get("E:\\动漫2.png"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
//创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (fr.read(buffer)!=-1){
buffer.flip(); //将缓冲区由读模式转为写模式
fw.write(buffer);
buffer.clear(); //本轮写完之后一定要清空此次缓冲区数据
}
fw.close();
fr.close();
System.out.println("复制完毕!");
四、使用map映射复制大文件(大于2G)
FileChannel fr = FileChannel.open(Paths.get("E:\\TreeSet.wmv"), StandardOpenOption.READ);
FileChannel fw = FileChannel.open(Paths.get("E:\\TreeSet1.wmv"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
//这只创建了三个映射区,可以创建很多个
//只读 起始位置 映射区大小
MappedByteBuffer map1 = fr.map(FileChannel.MapMode.READ_ONLY, 0, 1024 * 1024 * 50);
MappedByteBuffer map2 = fr.map(FileChannel.MapMode.READ_ONLY, 1024 * 1024 * 50, 1024 * 1024 * 50);
MappedByteBuffer map3 = fr.map(FileChannel.MapMode.READ_ONLY, 1024 * 1024 * 100, fr.size()-1024 * 1024 * 100);
fw.write(map1);
fw.write(map2);
fw.write(map3);
fw.close();
fr.close();
System.out.println("复制成功!");
五、Selector(轮巡器)
可以使用轮巡器实现非阻塞式网络通信
//服务端
public static void main(String[] args) throws IOException {
//创建ServerSocketChannel
ServerSocketChannel ssc = ServerSocketChannel.open();
//设为非阻塞
ssc.configureBlocking(false);
//绑定地址 端口号
ssc.bind(new InetSocketAddress("127.0.0.1", 11100));
//创建选择器
Selector selector = Selector.open();
//注册选择器
ssc.register(selector, SelectionKey.OP_ACCEPT);
while (selector.select()>0){
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey next = iterator.next();
if (next.isAcceptable()){
SocketChannel socketChannel = ssc.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
}else if(next.isReadable()){
//获取SocketChannel
SocketChannel channel = (SocketChannel)next.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int len=0;
while ((len= channel.read(buffer))>0){
buffer.flip();
System.out.println(new String(buffer.array(),0,len));
buffer.clear();
}if(len==-1){
channel.close();
}
}
iterator.remove();
}
}
}