NIO学习笔记--Buffer基础

Java NIO中 buffer用于和NIO通道进行交互,数据是从通道读入缓冲区,从缓冲区写入到通道中;
本质上Buffer对象是在内存中开辟的一段连续空间,用来临时存放数据;

1.Buffer基本用法和类型:

Buffer读写顺序步骤:

写入数据时,buffer会记录写入的数据量,当读取数据时,需要通过flip()方法将Buffer从写模式切换成读模式,读完了所有数据,调用clear()/compact()方法来清除数据(笔记:clear()方法会清空整个缓冲区,compact()方法会清除已读取的数据,并将未读数据移到起始位置,将position移到未读数据后)即:写入->读取->清除

buffer的实现:

ByteBuffer   CharBuffer   DoubleBuffer  FloatBuffer  IntBuffer   LongBuffer    ShortBuffer

可以通过这些类型来操作缓冲区中的字节,还有一个特殊的Buffer类型,用于表示内存映射文件

//读取Buffer属性的工具方法
public void __showBuffer(Buffer buffer){
    System.out.println("position:"+buffer.position()+" limit:"+buffer.limit()+" capacity:"+buffer.capacity());
}

2.Buffer的capacity,position和limit

Buffer的三个属性capacity,position,limit;
capacity指Buffer的容量,position和limit的含义由Buffer是读模式还是写模式决定

(备注:这里的读和写模式只是我们的习惯,系统不会限定读或者写,读取一个未写入数据的buffer单元会得到一个空格)

@Test
public void BufferDemo1(){
	// 获取buffer对象
	CharBuffer buffer = CharBuffer.allocate(26);
	__showBuffer(buffer);
	Character a_01 = buffer.get(0);
	System.out.println(a_01.toString());
}

得到:

position:0 limit:26 capacity:26

position:0 limit:26 capacity:26

▪ capacity 容量位:

指Buffer的容量,当buffer容量满了,需要将其清空(通过读数据或者清除数据)才能继续写数据

▪ position 操作位:

当前操作的位置,当写入数据时,position表示当前位置,每写入一个数据,会向前移动到下一个可插入数据的Buffer单元,初始值为0,最大值为capacity(笔记:当等于capacity时,表示容量已满,不能再移动,再次移动会抛出 java.nio.BufferOverflowException 异常)

当读取数据时,即从某个特定的位置读:当将Buffer从写模式切换到读模式,position会被重置为0,当从Buffer的position处读取数据时,position向前移动到下一个可读位置.

▪ limit限制位:

操作能到的最大位置

当写入数据时,limit表示最多能向Buffer写入多少数据,一般limit等于capacity

当读取数据时,limit表示最多能读取多少数据,切换到读模式使limit会被设置成写模式下的position值(设置成写入的数据量),

3.Buffer的获取

Buffer的shi类都有一个allocate方法可以获得一个Buffer对象,,一个新的Buffer对象默认position为0,limit和capacity等于Buffer的容量,可以通过position(int i),limit(int i)的方法设置position,limit的值

4.Buffer基本用法

写入数据两种方式:
a. 从Channel写到Buffer
eg: int bytesRead = inChannel.read(buf);
b. 通过put方法写入数据(具体可查api)
eg: put(byte b),put(byte[] src),put(byte[] src,int offset,int length),
put(ByteBuffer src),put(int index,byte b).
flip()方法:
将Buffer从写模式切换到读模式,会将position设为0,并将limit设置为之前position的值,即:limit表示可读数据量,
读取数据两种方式:
a. 从Buffer读取到Channel  eg: int bytesWritten = inChannel.write(buf)

b. 通过get()方法读取数据 eg: get(),get(byte[] dst),get(byte[],int offset,int length),get(int index)

@Test
public void BufferDemo2(){
    char[] chars = new char[26];
    for (int i = 0; i < chars.length; i++) {
    chars[i]=(char) ('a'+i);
    }
    //获取buffer对象
    CharBuffer buffer = CharBuffer.allocate(27);
    __showBuffer(buffer);
    //写入数据
    buffer.put(chars);
    __showBuffer(buffer);
    //反转缓冲区,
    buffer.flip();
    __showBuffer(buffer);	
}

得到:

position:0 limit:27 capacity:27
position:26 limit:27 capacity:27
position:0 limit:26 capacity:27

rewind()方法:

Buffer.rewind()将position设回0,limit不变,可以重新读取Buffer中的所有数据;

@Test
public void BufferDemo3(){
	//获取buffer对象
	CharBuffer buffer = CharBuffer.allocate(26);
	//写入数据	
	buffer.put(new char[]{'a','b','c','d','e'});
	__showBuffer(buffer);
	buffer.rewind();
	__showBuffer(buffer);		
}

得到

position:5 limit:26 capacity:26
position:0 limit:26 capacity:26

clear()与compact()方法:
调用clear方法,position会被设置为0,limit会被设置为capacity的值,换句话说,Buffer 被清空了,但Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往Buffer里写数据。

调用compact()方法,会将所有position后面的数据拷贝到Buffer起始处,然后将position设为最后一个未读元素后面,limit属性设置为capacity,Buffer进入写模式;(笔记:未读元素指position到limit之间的内容,即使buffer单元中没有元素)

遍历char数据工具类

void  __showArray(char[] arr){
	for (char c : arr) {
		System.out.print(c+"-");
	}
	System.out.println();
}

clear方法:

@Test
public void BufferDemo4(){
	//获取buffer对象
	CharBuffer buffer = CharBuffer.allocate(26);
	//写入数据	
	buffer.put(new char[]{'a','b','c','d','e','f','g'});
	__showBuffer(buffer);
	__showArray(buffer.array());
	//调用clear方法
	buffer.clear();
	__showBuffer(buffer);
	buffer.put(new char[]{'q','w','e','r'});
	__showBuffer(buffer);
	__showArray(buffer.array());
}
结果:
position:7 limit:10 capacity:10
a-b-c-d-e-f-g- - - -
position:0 limit:10 capacity:10
position:4 limit:10 capacity:10
q-w-e-r-e-f-g- - - -

调用compact()方法

@Test
public void BufferDemo5(){
	//获取buffer对象
	CharBuffer buffer = CharBuffer.allocate(10);
	//写入数据	
	buffer.put(new char[]{'a','b','c','d','e','f','g'});
	__showBuffer(buffer);
	__showArray(buffer.array());
	//调用compact方法
	buffer.compact();
	__showBuffer(buffer);
	buffer.put(new char[]{'q','w','e','r'});
	__showBuffer(buffer);
	__showArray(buffer.array());
}
得到
position:7 limit:10 capacity:10
a-b-c-d-e-f-g- - - -
position:3 limit:10 capacity:10
position:7 limit:10 capacity:10
 - - -q-w-e-r- - - -
mark()与reset()方法

调用mark()方法,标记其中一个特定的位置.之后可以通过调用reset()方法使position直接定位到mark位置.

@Test
public void BufferDemo6(){
	//获取buffer对象
	CharBuffer buffer = CharBuffer.allocate(10);
	//写入数据	
	buffer.put(new char[]{'a','b','c','d','e','f'});
	__showBuffer(buffer);
	//调用mark方法
	buffer.mark();
	buffer.put(new char[]{'q','w','e','r'});
	__showBuffer(buffer);
	//调用reset()方法
	buffer.reset();
	__showBuffer(buffer);
}

equals()与compare to()比较Buffer方法
剩余元素:从position到limit之间的元素
equals方法相等条件:1.相同的类型;2.Buffer中剩余的元素个数相等3.Buffer中所有剩余元素都相同( 笔记:即equals只比较剩余元素)

compare to方法:小于的条件:比较剩余元素第一个不相等的元素小于另一个Buffer的元素,或者第一个Buffer的元素个数小于另一个

个人总结:buffer中,三个重要属性capacity表示buffer的容量,position表示buffer现在操作的位置,limit表示当前操作的界限位置,buffer的api通过操作这这三个属性达到操作buffer中数据的功能


资料来源:

NIO官方文档:http://tutorials.jenkov.com/java-nio/index.html

并发编程网:ifeve.com/overview/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值