本质上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/