NIO介绍
Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API。
- Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
本文主要介绍ByteBuffer的常用方法
- Buffer 以下实现
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
一、首先介绍三个参数
- capacity
- position
- limit
String text = "123456789";
ByteBuffer byteBuffer = ByteBuffer.allocate(15);
byteBuffer.put(text.getBytes());//将text复制到缓冲区
//TODO 开始都去缓冲区,如果不进行flip,那么预测,byteBuffer lim=15,pos=9,cap=15
System.out.println(byteBuffer);//java.nio.HeapByteBuffer[pos=9 lim=15 cap=15]
//虽然pos等于9但是因为索引是从0开始的,那么在预测pos 8为止等于上面text的9
System.out.println("预测pos 8为止等于:" + (char) byteBuffer.get(8));//预测成功:预测pos 8为止等于:9
FIXME 由此解释:position limit capacity
- position在未写入数据时候为0,当写入数据,就变为写入数据长度的下一个可写的位置
text最后一个数的索引位置是8,所以在byteBuffer中position下一个可以写的位置就是9,而8位置,就对应了text中最后一个数9
- capacity等于缓冲区的长度
- limit可以理解为写入数据的长度,当初始化没有数据时候,就等于capacity的长度。而当写入数据时候就变成了数据的长度
当读到这里,就可以对预测的明白了。
二、开始新的高级学习,读写操作
- flip(); 这个方法用于重置pos位置当写的时候位置为可写的位置,但是读的时候如果不重置,读取的就是没有数据的位置.用于读写转换
String text = "123456789";
ByteBuffer byteBuffer = ByteBuffer.allocate(15);
byteBuffer.put(text.getBytes());//将text复制到缓冲区
//开始读取
//我们要从0开始读,到lim位置,而这个方法就是把pos=0,lim=数据长度
byteBuffer.flip();//预测:pos=0,lim=9,cap=15
System.out.println(byteBuffer);//java.nio.HeapByteBuffer[pos=0 lim=9 cap=15]
for (int i = 0; i < byteBuffer.limit(); i++) {
System.out.print((char) byteBuffer.get(i));//123456789
}
假设不进行flip就会读空数据,那么由于我们转为char 所以出来就是乱码123456789[][][]
- clear();这个方法会把pos=0 lim=15 cap=15,等于把byteBuffer对象重置了
byteBuffer.clear();
System.out.println(byteBuffer);
- rewind();这个方法会重置pos=0 其他维持原样 为读取有效数据
- get();获得最后limit位置数据
- get(int index);获取制定位置数据
- get(byte arr);复制有效数据到arr数组
- put(byte arr);把arr数据写入到缓冲区
- put(int index,byte arr);把arr写入到指定位置
三、 标记方法,具有回滚功能,这两个方法不解释,只演示
- mark();
- reset();
byteBuffer.put(text.getBytes());//因为上面已经清理了,所以在此将text复制到缓冲区
for (int i = 0; i < 8; i++) {
if (i == 1) {
byteBuffer.mark();//标记1位置开始写新数据
byteBuffer.put(1, ((byte) '4'));//此时预测数据为:143456789
}
}
// byteBuffer.reset();//回到标记位置
byteBuffer.flip();
for (int i = 0; i < byteBuffer.limit(); i++) {
System.out.print((char) byteBuffer.get(i));//143456789 ,预测成功
}
四、复制缓冲区
byteBuffer.clear();
byteBuffer.put(text.getBytes());//将text复制到缓冲区
ByteBuffer byteBuffer1 = byteBuffer.duplicate();
System.out.println(byteBuffer); //[pos=9 lim=15 cap=15]
System.out.println(byteBuffer1); //[pos=9 lim=15 cap=15]
//但是当修改一个地方,另一个缓冲区也会变化 ,这个变化是内容变化,但是pos lim cap不改变
//开始试验,将1的插入新数据
byteBuffer1.flip(); //重置写
byteBuffer1.put((byte) 'A');
System.out.println(byteBuffer); //[pos=9 lim=15 cap=15]
System.out.println(byteBuffer1); //[pos=10 lim=15 cap=15] 因为添加了,所以pos位置变了
//开始获取,这个两个最后一个数据,预测,都是A。
System.out.println((char) byteBuffer.get(0)); //A
System.out.println((char) byteBuffer1.get(0)); //A
此方法有个特殊的地方就是:当修改一个地方,另一个缓冲区也会变化 ,这个变化是内容变化,但是pos lim cap不改变
附录
- NIO是高效的IO处理方式,如果感兴趣的笔者推荐可以和笔者一起深入学习Netty框架,快速开发高性能、高可靠性的网络服务器和客户端程序
- 其次Buffer的使用方法远不止如此,笔者这里只使用常用方法