NIO流的学习
Posted auge
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NIO流的学习相关的知识,希望对你有一定的参考价值。
NIO的使用
一)、什么叫NIO?
定义:是一套新的Java I/O标准, 在java1.4中被纳入JDK中。
二)、NIO的实现方法
NIO是基于块的, 以块为基本单位处理数据。
标准的I/O是基于流实现的,以字节为单位处理数据。
三)、NIO的特性
1).为所有的原始类型特供Buffer支持
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
2).字符集编码解码解决方案,使用java.nio.Charset
3) .增加通道(Channel)对象,做为新的原始的I/O抽象
4).支持锁和内存映射文件的文件访问接口
5).提供了基于Selector的异步网络I/O
四)、NIO的两个重要组件
Buffer: 缓冲, 是一块连续的内存块,是NIO中读写数据的中转地。
Channel: 通道, 表示缓冲数据的源头或目的地。
Buffer和Channel的关系:
Channel作为数据的源头:从Channel中写数据到Buffer
Channel ---------> Buffer
Channel作为数据的目的地:从Buffer中写出数据到Channel
Channel <--------- Buffer
五)、NIO的Buffer类族和Channel
Buffer: 是一个抽象类,JDK为每一种Java原生类型都创建了一个Buffer.
注: 除了ByteBuffer外,其它每一种Buffer都具有完全一样的操作。
原因:ByteBuffer多用于绝大多数数标准I/O操作的接口。
Channel: 是一个双向通道,既可读也可写。
注:应用程序中不能直接对Channel进行读写操作,在读取Channel时,需要先将数据读入到相对应的Buffer中,然后在Buffer中进行读取。
使用Buffer读取文件:
public class Nio_Buffer_Channel {
public static void main(String[] args) throws IOException {
//获取一个输入流对象
FileInputStream fin = new FileInputStream("d:/a.txt");
//获取输入流对象的通道,作为数据的源头
FileChannel fileChannel = fin.getChannel();
//创建一个Buffer对象
ByteBuffer buffer = ByteBuffer.allocate(1024);
//从通道中读取数据到Buffer中
fileChannel.read(buffer);
//关闭通道
fileChannel.close();
buffer.flip();
}
}
使用Buffer完成文件的复制:
public class Nio_Buffer_Copy {
public static void main(String[] args) throws IOException {
//输出流对象
FileOutputStream fout = new FileOutputStream("d:/c.txt");
//输入流对象
FileInputStream fin = new FileInputStream("d:/a.txt");
//输出流的通道,数据的目的地
FileChannel writeChannel = fout.getChannel();
//输入流的通道,数据的源头
FileChannel readChannel = fin.getChannel();
//Buffer对象
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(true){
buffer.clear();
//返回读取数据的大小
int len = readChannel.read(buffer);
if(len == -1){
break;
}
buffer.flip();
writeChannel.write(buffer);
}
}
}
结果:
0
11
0
11
0
六)、深入学习Buffer
主要属性:
//标志位
private int mark = -1;
//写模式:当前缓冲区的位置,从Position的下一个位置写数据
//读模式:当前缓冲区的读位置,将从此位置后,读取数据
private int position = 0;
//写模式: 缓冲区的实际上限,总是小于等于容量,通常等于容量
//读模式: 代表可读取的总容量,和上次写入的数据量相等
private int limit;
//写模式: 缓冲区的总容量上限
//读模式: 缓冲区的总容量上限
private int capacity;
对Buffer进行claer()和flip()操作时lmint和position的变化
public class Filp_Clear {
public static void main(String[] args) {
//创建具有15个字节的Buffer对象
ByteBuffer buffer = ByteBuffer.allocate(15);
System.out.println("存入元素后position和limit的变化==>"+"position:"+buffer.position()+" limit:"+buffer.limit()+" capacity:" +buffer.capacity());
//向Buffer中存入数据
for(int i = 0 ; i < 10 ; i++){
buffer.put((byte)i);
}
//存入元素后position和limit的变化
System.out.println("存入元素后position和limit的变化==>"+"position:"+buffer.position()+" limit:"+buffer.limit()+" capacity:" +buffer.capacity());
buffer.flip();
//flip后position和limit的变化
System.out.println("flip后position和limit的变化==>"+"position:"+buffer.position()+" limit:"+buffer.limit()+" capacity:" +buffer.capacity());
for(int i = 0 ; i < 5 ; i++){
System.out.print(buffer.get()+" ");
}
System.out.println();
//读取Buffer元素后position和limit的变化
System.out.println("读取Buffer元素后position和limit的变化==>"+"position:"+buffer.position()+" limit:"+buffer.limit()+" capacity:" +buffer.capacity());
buffer.rewind();
System.out.println("rewind==>"+"position:"+buffer.position()+" limit:"+buffer.limit()+" capacity:" +buffer.capacity());
buffer.flip();
//第二次flip后position和limit的变化
System.out.println("第二次flip后position和limit的变化==>"+"position:"+buffer.position()+" limit:"+buffer.limit()+" capacity:" +buffer.capacity());
buffer.clear();
//clear后position和limit的变化
System.out.println("clear后position和limit的变化==>"+"position:"+buffer.position()+" limit:"+buffer.limit()+" capacity:" +buffer.capacity());
}
}
运行结果:
存入元素后position和limit的变化==>position:0 limit:15 capacity:15
存入元素后position和limit的变化==>position:10 limit:15 capacity:15
flip后position和limit的变化==>position:0 limit:10 capacity:15
0 1 2 3 4
读取Buffer元素后position和limit的变化==>position:5 limit:10 capacity:15
rewind==>position:0 limit:10 capacity:15
第二次flip后position和limit的变化==>position:0 limit:0 capacity:15
clear后position和limit的变化==>position:0 limit:15 capacity:15
结果分析:
1).当第一次创建Buffer对象时
position = 0, capacity = limit = Buffer数组容量大小
2).往Buffer添加数据
position = 数组所占数据的大小,capacity = limit = Buffer数组容量大小
3).buffer.flip()操作
position = 0, limit = 数组中所占元素的大小,即原position值, capacity = Buffer数组容量大小
4).buffer.get()获取元素
position = 获取元素的个数,limit = 数组中所占元素的大小,capacity = Buffer数组容量大小
5).再次buffer.flip()
position = 获取元素的个数,limit = position值, capacity = Buffer数组容量大小
注: 当执行flip操作,limit值总是等于上一次的position值
6).buffer.clear
position = 0, capacity = limit = Buffer数组容量大小
总结:
i. put(): position = 数组元素个数 , limit 和 capacity 不变
ii. flip(): position = 0, limit = 原position值, capacity 不变
iii. rewind(): position = 0, limit 和 capacity 不变
iiii. claer(): 回到初始状态,position = 0, capacity = limit = Buffer数组容量大 小。
以上是关于NIO流的学习的主要内容,如果未能解决你的问题,请参考以下文章