Java NIO - Buffer 基础 -1

Java NIO使用了操作系统层对对非阻塞IO的支持。不再是基于Stream的数据传输,而是基于Buffer的数据传输。NIO最大的改变有:非阻塞IO,可以减少线程数量;Buffer传输数据机制,这个应该是为了迎合底层实现,提高效率;同样也是因为使用了底层直接的IO API,所以IO的效率也提高了。

Buffer作为数据的载体,Java NIO中为每种基本数据类型(boolean除外)都提供了一种Buffer实现。使用最多的还是ByteBuffer。下面的Buffer即可能指代Buffer,也可能指代ByteBuffer。

Buffer的创建有几种方式,可以把一个byte数组包装成一个Buffer;可以直接new一个buffer,指定buffer的capacity;也可以调用allocate方法,创建一个direct buffer。

无论通过何种方式创建出来的buffer,在实际使用的时候都可以看作一样的。

buffer有几个变量时不得不谈的: 0<=mark<=position<=limit<=capacity。

mark的值是用来暂时保存position值的,这个在buffer的某些方法中会用到。

position是指向下一个将要被读出的元素或者写入下一个元素的位置。

limit是最后一个有效元素的位置。只对读数据有效。

capacity是buffer的最大容量,写操作的时候不能超过此索引值。buffer一旦创建,这个值就不再可以更改。

buffer的读写操作,都是操作数组上的值和这几个变量。

首先说写操作。

在写操作之前,如果确定buffer中的数据已经没用了,可以调用clear方法先。这个方法会将mark变量设为-1,position为0,limit为capacity。可以看出,这是清空了buffer,做好了写入数据的准备。

写入数据是通过put方法,可以每次put一个元素,也可以每次put一个数组。put一个数组的参数是(arr, offsite, len)。这个很直接,没啥好说的。

每次调用put方法之后,position变量都会增加put进去元素的个数。也就是说,position变量始终是指向下一个空白的位置,等待新的元素写入。如果在position到达capacity后还尝试放入元素,则会抛出BufferOverflowException。

然后是读取操作。

当写入完毕后,下一步就应该是对buffer进行读取操作了。在读取之前,必须调用flip方法完成读写的转换。

调用flip后,limit=position, position=0,mark=-1;可以看到,这已经为读取做好了准备:程序可以从position开始读。读取使用get方法,每次读取一个元素,position就会加1,直到limit结束。这时候,limit=position。当然,读取的时候也可以一次读取多个,只要传入一个数组就可以了。这个和put方法一样。需要注意的是,如果指明的需要读取的元素多于还剩余的元素个数,则会抛出BufferUnderflowException。

除了基本的读写操作,还有一些别的方法值得记住。

rewind:写入数据的时候,Channel中如果有足够的数据,则会尽量填满position到limit。 如果调用clear方法,limit将会被设置为capacity,如果想读取指定长度的数据,而不是填满整个buffer,则可以先设置好limit的值,然后调用rewind方法。这个方法会将position置0,mark设置为-1,但是不会改变limit的值。

compact:写入数据的时候,如果接收方没有完全接受数据,也就是说,调用完write(buffer)之后,position<limit,这时候,如果调用clear方法继续读取数据,则会丢失部分没有写入的数据。对于这种情况,可以调用compact方法,它会将位于position和limit之间的数据挪到开头(从0开始也就是),然后设置position的值为limit-position,limit设置为capacity。这样就可以继续用这个buffer来读取数据了。

reset:Buffer还有一个变量叫做mark,这个值介于0和position之间,可以认为是程序在get数据的时候,发现一个特殊的位置,用mark来标记住。然后继续读取数据。如果想把position设置为mark,就可以调用reset方法。这个方法只改变position的值。注意,很多方法都会将mark置为-1,也就是不可用,比如clear,flip,rewind,(按说compact应该也需要,但是没有,不知道为什么),这时候调用reset就会抛异常。

clear,put,flip,get,还有compact,rewind以及clear。这些算是操作buffer的基本操作吧。

posted @ 2011-09-17 23:07  深夜两点  阅读(589)  评论(0编辑  收藏  举报