IO、BUFFER、BIO、NIO介绍

缓冲区buffer介绍

缓冲区(Buffer)就是在内存中预留指定大小的存储空间用来对I/O的数据做临时存储,这部分预留的内存空间叫缓冲区。

使用缓冲区有两个好处:
1、减少实际物理读写次数
2、缓冲区在创建时就被分配内存,这块内存区域一直被重用,可以减少动态分配和回收内存的次数

一般在实际过程中,我们一般是先将文件读入内存,再从内存写入到别的地方,这样在输入输出过程中我们都可以用缓存来提升IO性能。

在java nio中,缓冲区的作用也是用来临时存储数据,可以理解为是I/O操作中数据的中转站。缓冲区直接为通道(channel)服务,写入数据到通道或从通道读取数据,这样利用缓冲区数据来传递就可以达到对数据高效处理的目的。在nio中主要有八种缓冲区类(其中MappedByteBuffer是专门用于内存映射的一种ByteBuffer):
ByteBuffer(常用),CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer

2、Fields

所有缓冲区都有4个属性:capacity、limit、position、mark,并遵循mark<=position<=limit<=capacity,下表时对这4个属性的解释:

字段 作用
position 当前读到的位置
limit 当前写到的位置
capacity 容量
mark 标记,调用mark()来设置mark=position,在调用reset()可以让position恢复到标记位置

3、另外一些常用的方法

方法 描述
limit(),limit(10) 前者get,后者set
reset() 把position设置成mark的值
clear() position=0,limit=capacity,mark=-1
flip() limit=position,position=0,mark=-1;将缓冲区状态由存数据变为准备取数据
rewind() 把position设为0,mark设为-1,不改变limit的值
remaining() return limit-position
hasRemaining() return position < limit,是否还有未读内容
compact 把position到limit间的内容移到0到limit间,position和limit的取值分别变为limit-position、capacity;
也即将未读的内容拷贝到缓冲区开头,现在buffer准备好写数据,但是不会覆盖未读的数据;
如果先将position设置到limit,再compact,那么相当于clear
get() 相对读,从position读取一个byte,并将position+1,为下次读写做准备
get(int index) 绝对读,读取byteBuffer底层bytes下标为index的byte,不改变position
get(byte[]dst,int offset,int length) 从position开始相对读,读length个byte,并写入dst下标从offset到offset+length的区域
put(byte b) 相对写,向position写入一个byte,并将position+1,为下次读写做准备
put(int index,byte b) 绝对写,想byteBuffer底层的bytes中下标为index的位置插入byte b,不改变position
put(ByteBuffer src) 用相对写,把src中可读的部分(position-limit)写入到此byteBuffer)
put(byte[]src,int offset,int length 将src数组中offset到offset+length的数据写入到position之后,并将position+length

4.Buffer 写读原理图:

第一步:初始化状态下的数组new byte[5],position为0,limit为5,capacity为5.

第二步:写入两个字节后  >>  position为2,limit为5,capacity为5.

第三步:因为所有可操作的数据处于position和limit之间,所以读之前要调用 flip()方法,flip调用之后,position为0,limit为2.

             flip方法源代码展示:

                                            

第四步:读取状态,读取完毕后:position为2,limit为2。

第五步:读完之后要面临再次写入数据,在写入数据之前要处于清空状态,调用 clear()方法,调用clear后 position为0,limit为5

              备注:所谓的处于清空状态或者调用clear方法并不是清空数组中之前写入的两个字节的数据,只是单出的改变position和limit的位置,上一次读入的数据依然存在。

           clear()方法源码展示:

                                           

第六步:再次写入一个字节的数据,position为1,limit为5.   看图理解步骤。

            备注:读数据前先flip:因为buffer可操作的数据处于position和limit之间,否则读不出数据。

                       写数据前先clear:可能是为写操作提供更宽阔的空间吧

以上原理代码测试:

package com.***.demo;
import java.nio.ByteBuffer;
public class TestBuffer {
	public static void main(String[] args) {
		//1.创建buffer
		byte[] bytes=new byte[5];
		ByteBuffer buffer=ByteBuffer.wrap(bytes);
		System.out.println("初始状态 :capacity:"+buffer.capacity()+",position:"+buffer.position()+",limit:"+buffer.limit());
		 //初始状态:capacity为5 position为0  limit为5
		//写2个字节
		buffer.put((byte)'a');
		buffer.put((byte)'b');
		System.out.println("写2字节 :capacity:"+buffer.capacity()+",position:"+buffer.position()+",limit:"+buffer.limit());
         //写两个字节:capacity为5 position为2  limit为5
		buffer.flip();
		
		//读两个字节
		while(buffer.hasRemaining()){
			System.out.println(buffer.get());
		}
		System.out.println("读完2字节 :capacity:"+buffer.capacity()+",position:"+buffer.position()+",limit:"+buffer.limit());
		 //读完两个字节:capacity为5 position为2  limit为2
		buffer.clear();
		buffer.put((byte)'c');
		
		buffer.flip();
		//读两个字节
	
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值