NIO学习(二) buffer

buffe有很多类型(charbuffer,doublebuffer,shortbuffer等),因为java底层用的字节传输的,主要学习bytebuffer

1. 认识buffer索引

NIO学习(二) buffer_第1张图片

position: 当前位置

limit: 限制值

capacity: buffer的总容量

mark:标记值,使用mark()函数可以标记当前position,在使用reset()后会将position重置为mark值,默认为-1,即没有mark值


常用方法:

mark():将mark设置为position

get():读取position位置的数据,使position位置后移

put():在position位置写入数据,使position位置后移

remaining():获取position和limit之间的元素个数

hasRemaining():判端position和limit之间是否有元素

flip(): 将position设置为0,limit设置为position,mark设为-1,在读取数据前会调用这个方法

clear():注意到这个并不是清除缓冲区数据,将position设为0,并将limit设为capacity(buffer的容量大小),一般在写入buffer前会调用这个方法

reset():将position设置为mark值

rewind():将position设为0,并丢弃标识位

compact():将position,limit间的数据复制到缓冲区的开头,为后续的put/get操作让出空间,调用这个方法后,

position的值为复制数据的长度,limit为capacity,保守使用这个方法,复制操作耗费资源

2. ByteBuffer的创建

ByteBuffer.wrap(byte[] array)/wrap(array,offset,length): 使用一个现有的数组来创建缓冲区

如果没有指定offset,length ,position=0,limit = length,否则position=offset,limit=length

这个数组称为后援数组,对后援数组的修改都将改变缓冲的数据,反之,亦然


ByteBuffer.allocat(int capacity)

唯一区别wrap方法,allocate创建了自己的后援数组,调用array方法可以获取后援数组的引用。


注意:创建的缓冲区数据,都会放在后援数组中,通常底层平台,不能直接使用这些缓冲区进行i/o操作,需要操作系统使用自己的缓冲区进行i/o,将数组复制到后援数组中。这种操作对于大量的i/o操作,很耗费系统性能

java提供了直接缓冲区来解决,使用直接缓冲区,java将从平台能够直接进行i/o操作的存储空间中为缓冲区分配后援数组,避免了数据的复制过程。

直接缓冲区的创建:ByteBuffer buffer = ByteBuffer.allocatDirect(int capacity)

note:1. 直接缓冲不一定创建成功,可以使用isDirect()方法进行检查

       2. 直接缓冲区没有后援数组,调用array,arrayoffset方法将抛出异常

       3. 分配和销毁直接缓冲区比分配和销毁非直接缓冲区消耗更多的系统资源,只有在i/o操作长时间使用时,才去分配直接缓冲区


3. buffer透视:duplicate()slice()

   nio提供了方法创建和给定缓冲区共享内容的新缓冲区,这些新缓冲区的buffer索引如下所示,但是和原来的缓冲区共享一个后援存储空间,任何对新缓冲区的修改都将反应到原缓冲区上。

NIO学习(二) buffer_第2张图片

NIO学习(二) buffer_第3张图片

asReadOnlyBuffer和duplicate创建的缓冲区类似,只是创建的新缓冲区是只读的,(可用isReadOnly检查缓冲区是否只读),任何对只读缓冲区内容修改的方法都将抛出异常,甚至只读缓冲区调用slice,duplicate创建的新缓冲区也是只读的。

bytebuffer能够创建一个视图缓冲区,用于将bytebuffer的内容解释为其他基本类型,调用上面的asCharbuffer,..等方法,新创建的基本类型的缓冲区position等于0,limit和capacity等于总字节数/元素类型对应的字节数。

实例:

package cn.itcast.nio;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.ShortBuffer;

/**
 * 视图缓冲区,实现不同基本类型数据buffer的读取和写入
 * @author zhouy
 *
 */
public class ByteBuffTest {	
	public static void main(String[] args) {
		ByteBuffer buffer = ByteBuffer.wrap(new byte[]{0,0,0,0,0,0,'a'});
		
		//bytebuffer
		buffer.rewind();//类似flip操作,不过将position设为0,标识位失效,limit不变
		System.out.print("ByteBuffer");
		while(buffer.hasRemaining()){
			System.out.println(buffer.position()+"->"+buffer.get()+",");
		}
		
		//charbuffer
		buffer.rewind();
		CharBuffer charBuffer = buffer.asCharBuffer();
		//转为charbuffer后,limit等于7/2 =3,position可选的值0->2
		System.out.println("charbuffer:");
		while(charBuffer.hasRemaining()){
			System.out.println(charBuffer.position()+"->"+charBuffer.get()+",");
		}
		//shortBuffer
		buffer.rewind();
		ShortBuffer shortBuffer = buffer.asShortBuffer();
		System.out.println("shortbuffer");
		while(shortBuffer.hasRemaining()){
			System.out.println(shortBuffer.position()+"->"+shortBuffer.get()+",");
		}
	}

}

输出:

ByteBuffer0->0,
1->0,
2->0,
3->0,
4->0,
5->0,
6->97,

charbuffer
0->?,
1->?,
2->?,

shortbuffer
0->0,
1->0,
2->0,





你可能感兴趣的:(NIO)