java NIO(十) 缓冲区——compact方法介绍

来源:互联网 发布:沈阳seo新浪博客 编辑:程序博客网 时间:2024/06/05 04:54


注意java6帮助文档对compact方法的介绍

compactpublic abstract ByteBuffer compact()压缩此缓冲区(可选操作)。 将缓冲区的<strong><em><u>当前位置和界限之间的字节(如果有)</u></em></strong>复制到缓冲区的开始处。即将索引 p = position() 处的字节复制到索引 0 处,将索引 p + 1 处的字节复制到索引 1 处,依此类推,直到将索引 limit() - 1 处的字节复制到索引 n = limit() - 1 - p 处。然后将缓冲区的位置设置为 n+1,并将其界限设置为其容量。如果已定义了标记,则丢弃它。 将缓冲区的位置设置为复制的字节数,而不是零,以便调用此方法后可以紧接着调用另一个相对 put 方法。 从缓冲区写入数据之后调用此方法,以防写入不完整。例如,以下循环语句通过 buf 缓冲区将字节从一个信道复制到另一个信道:  buf.clear();          // Prepare buffer for use  while (in.read(buf) >= 0 || buf.position != 0) {     buf.flip();     out.write(buf);     buf.compact();    // In case of partial write }返回:此缓冲区 抛出: ReadOnlyBufferException - 如果此缓冲区是只读缓冲区

上文中的加黑加粗斜体部分表明了,为什么compact通常与flip方法合用:在通道(channel)间进行复制的时候,我们知道put或者get方法会通过标记pos的位置来标记字符位置,

flip在限制limit后,调用put方法(如上文中的例子),此时我们调用compact方法会执行两个动作,1、清除之前已经写如果的字符;2、根据上文加黑加粗斜体部分表明pos的位置将在0,通过这两步达到我们的预期,这就是为什么此时单纯的调用filp方法不行的原因。

下面通过两个图片形象说明compact的动作:

执行compact之前缓冲区在内存中的表现:


compact后缓冲区的表现:


由上图可看:分为两点:
1、释放一部分数据,即pos所指位置前移至零处;
2、重新填充,如果要重新填冲,pos的位置要慎重,这就是为什么最后pos的位置在4的原因
经过这两步之后形成所谓的压缩


下面再给出通道间复制字符串的代码:

package com.z;import java.nio.ByteBuffer;import java.nio.channels.Channels;import java.nio.channels.ReadableByteChannel;import java.nio.channels.WritableByteChannel;public class ChannelCopy {public static void main(String[] args) throws Exception{ReadableByteChannel src = Channels.newChannel(System.in);WritableByteChannel des = Channels.newChannel(System.out);copy1(src,des);src.close();des.close();}private static void copy1(ReadableByteChannel src, WritableByteChannel des) throws Exception{ByteBuffer tmp = ByteBuffer.allocate(16 * 1024);while(src.read(tmp) != -1){tmp.flip();des.write(tmp);tmp.compact();}tmp.flip();while(tmp.hasRemaining()){des.write(tmp);}}}


0 0
原创粉丝点击