本文共 2706 字,大约阅读时间需要 9 分钟。
buffer是个抽象类,被各个原生数据类型的buffer继承,nio中channel是通过buffer进行数据读写操作的
buffer是双向操作,既可以读也可以写,实现buffer读写转化功能的,主要是buffer当中的各个属性字段
线程不安全
如何理解这几个字段具体的含义
比如在初始化一个长度为10的buffer之后,其capacity已经固定了,就是10,此时limit也可以是10,position当前并没有往数组中添加元素,position的索引就是0
buffer.put()添加两个元素之后
capacity的值还是10,(永久不变)
position下一个需要写的索引就是2
此时limit还是等于10,如果需要将已经写入的元素读取出来,也就是由原来的写入,变成读,需要buffer.filp()
这时候position=0, limit=2, capacity=10
进行元素读取,直到position=2, limit =2 ,capacity=10 不能继续再读下去
当把所有的元素都读取完之后,想要继续写入,再次执行buffer.flip()
position=0 ,limit =2 ,capacity=10 ,从0开始写入
* @return This buffer */public final Buffer flip() { limit = position; position = 0; mark = -1; return this;}这个就是源码中执行flip方法的操作,limit会记录当前读或者写的索引最大值,position从0开始读取,只到position=limit时,读取或者写入结束
使用NIO读取文件内容时容易出现的一个问题
public static void main(String[] args) throws Exception{ FileInputStream inputStream = new FileInputStream("input.txt"); //存在于根目录下的文件 FileOutputStream outputStream = new FileOutputStream("output.txt"); FileChannel fileInputChannel = inputStream.getChannel(); FileChannel fileOutputChannel = outputStream.getChannel(); ByteBuffer byteBuffer = ByteBuffer.allocate(1024); while (true){ byteBuffer.clear(); //如果将这段代码注释掉,执行结果会出现什么问题 int read = fileInputChannel.read(byteBuffer); if(-1 == read){ break; } byteBuffer.flip(); fileOutputChannel.write(byteBuffer); }}这里如果while循环中没有byteBuffer.clear() output.txt文件会一直不断地增加,程序处于死循环当中
原因在于:
第一次进入循环
step1: position=0, limit=capacity,当写入一定数据之后,(假设有5个字节)
position=5,limit=1024,capacity=1024
flip方法后
position=0,limit=5,capacity=1024,
将所有的数据读取完之后,position=5,limit=5,capacity=1024
第二次次进入循环:
read=0
flip方法之后
position=0,limit=5,capacity=1024
数组元素并未被清空,所以会一直读取第一次写入进去的字节,程序进入死循环
----------------------------------------------------------------------------------------
buffer中几个方法
clear() 是清空,重新开始写入数据,campact是将未读完的数据,拷贝一部分,保存,然后继续写入数据,会更加浪费内存,clear不能读取到之前写入的数据
在ByteBuffer, slice()方法是将当前ByteBuffer的属性拿过去,直接使用,数组使用的是同一个底层数组,所以不管是之前的ByteBuffer还是slice()方法返回的ByteBuffer,对数组的操作,两个buffer都会有影响
ByteBuffer scattering,gathering
Scattering: channel可以读取内容到一个buffer数组当中,按照数据顺序,会在第一个写满之后,写入下一个
Gathering: 将多个buffer的内容写入到channel当中
什么时候会用到Scattering和Gathering?
在使用自动义网络协议是,header,body可能是不同的内容,这个时候,可以使用两个不同长度的数据,来进行传递数据,而不需要使用特殊字符来进行分割,或者是截取固定长度的buffer
转载地址:http://gavti.baihongyu.com/