开发者社区> boxti> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

java nio之Buffer(一)

简介:
+关注继续查看
Buffer是一个包装了基本数据元素数组的对象,它以及它的子类定义了一系列API用于处理数据缓存。

一、属性
Buffer有四个基本属性:
1、capacity  容量,buffer能够容纳的最大元素数目,在Buffer创建时设定并不能更改
2、limit buffer中有效位置数目
3、position 下一个读或者写的位置
4、mark  用于记忆的标志位,配合reset()使用,初始值未设定,调用mark后将当前position设为值

四者关系:0 <= mark <= position <= limit <= capacity

二、API

package java.nio;
public abstract class Buffer {
public final int capacity( )
public final int position( )
public final Buffer position (int newPosition)
public final int limit( )
public final Buffer limit (int newLimit)
public final Buffer mark( )
public final Buffer reset( )
public final Buffer clear( )
public final Buffer flip( )
public final Buffer rewind( )
public final int remaining( )
public final boolean hasRemaining( )
public abstract boolean isReadOnly( );
}

支持链式调用,如:buffer.mark().position(5).reset( );
注意isReadOnly()方法决定了buffer是否可写。

三、操作
  以ByteBuffer为例,
1、访问,通过get(),get(index),其中get()从当前position位置读取,get(index)从index位置读取,不改变当前position,下面要说到的put也一样。
2、填充,通过put(byte),put(index,byte),按照绝对位置填充也是不改变当前position属性

3、flipping,试想,我们将填充完毕的buffer传递给socket输出,那么socket读取是依据position属性确定,就会从结尾后一位开始读,这样肯定是不正确的,如果要正确的读取我们先要:
  buffer.limit(buffer.position( )).position(0);
将limit设为position, 将position设为0,这个操作就叫flipping,API直接提供了这个操作:
  buffer.flip( );
特别注意,flip()方法会改变limit属性,将limit属性从capacity设置为当前position。rewind()方法与flip()类似,但是仅将position设为0,而不改变limit,通常用于重新读取已经被flip的buffer。flip()另一个注意点是,两次调用buffer的flip方法,将使得position和limit属性都为0。

4、迭代取元素:
for (int i = 0; buffer.hasRemaining( ), i++) {
myByteArray [i] 
= buffer.get( );
}

int count = buffer.remaining( );
for (int i = 0; i < count, i++) {
myByteArray [i] 
= buffer.get( );
}
ByteBuffer不是线程安全的,前一种方式适合并发访问,后一种方式效率更高。这两种方式都是一个一个取,效率都比批量取低。

5.clear()方法,将buffer重设为空状态,也就是设置limit=capacity,position=0,以便重复利用。

6.compact()方法,用于压缩buffer,这个方法在多次重复调用时是比较低效。

7.mark(),初始是未定义的,这适合如果调用reset将抛出InvalidMarkException。调用makr()后,将当前position设为mark以便reset时返回。注意,rewind( ), clear( ), and flip( )方法都将丢弃已经创建的mark。调用limit(index),positioon(index),如果index的值小于当前mark,mark也将被丢弃。

8.比较,可以通过equals()和compateTo()方法来比较两个buffer,前一个返回boolean,后一个返回0,-1,1。两个buffer equal的条件是:
1)类型相同
2)剩余元素的数目相等
3)剩余元素也一一相等

9、批量移动数据,为了更有效地进行数据传送,批量的数据存取肯定是不能少的,Buffer及其子类都有提供类似的方法,比如CharBuffer:
public CharBuffer get (char [] dst)
public CharBuffer get (char [] dst, int offset, int length)
public final CharBuffer put (char[] src)
public CharBuffer put (char [] src, int offset, int length)
public CharBuffer put (CharBuffer src)
public final CharBuffer put (String src)
public CharBuffer put (String src, int start, int end)


四、创建Buffer
    Buffer以及其子类都无法直接new,而必须把通过他们提供的工厂方法来创建。通常有两种方式:
1、allocate,例如
CharBuffer charBuffer = CharBuffer.allocate (100);
将在堆上分配一个可以存储100个字符的数组作为backing store。

2、wrap,包装一个已有的数组:
char [] myArray = new char [100];
CharBuffer charbuffer = CharBuffer.wrap (myArray);
注意,这样的方式创建的Buffer,将不会在堆上创建新的数组,而是直接利用myArray做backing store,这意味着任何对myArray或者buffer的修改都将影响到buffer或者myArray。可以通过public final boolean hasArray( )方法来判断是否拥有一个数组,通过array()方法取得这个数组。

五、复制Buffer
   其实这个复制也是“浅拷贝”,通过duplicate()方法将返回一个新创建的buffer,这个新buffer与原来的Buffer共享数据,一样的capacity,但是有自己的position、limit和mark属性。通过asReadOnlyBuffer()方法复制的buffer与duplicate()类似,但是是只读的,不能调用put。比较特别的是slice()方法,故名思议,类似切割一个Buffer出来,与duplicate类似,但是它将从原来Buffer的当前position开始,并且capacity等于原来Buffer的剩余元素数目,也就是(limit-position)。

文章转自庄周梦蝶  ,原文发布时间2008-02-22

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【Java 网络编程】NIO Buffer 简介 ( 概念 | 数据传输 | 标记 | 位置 | 限制 | 容量 | 标记 | 重置 | 清除 | 翻转 | 重绕 | 链式操作 )
【Java 网络编程】NIO Buffer 简介 ( 概念 | 数据传输 | 标记 | 位置 | 限制 | 容量 | 标记 | 重置 | 清除 | 翻转 | 重绕 | 链式操作 )
43 0
Java nio Buffer
nio buffer原理及使用
57 0
Java NIO 之 Buffer(缓冲区)
Java NIO Buffers用于和NIO Channel交互。 我们从Channel中读取数据到buffers里,从Buffer把数据写入到Channels. Buffer本质上就是一块内存区,可以用来写入数据,并在稍后读取出来。
13168 0
Java NIO(四)Buffer
根据Channel的使用我们可以知道,与NIO channel交互时使用Java NIO buffer。 如您所知,数据从channel读入缓冲区,并从缓冲区写入通道。
656 0
java nio之Buffer
  一、JAVA NIO 是在和channel交互的时候使用的。Channel将数据读入缓冲区,然后我们又从缓冲区访问数据。写数据时,首先将要发送的数据按顺序填入缓冲区。基本上,缓冲区只是一个列表,它的所有元素都是基本数据类型(通常为字节型).
806 0
Java NIO Buffer
Java Nio  1 Java NIO Tutorial 2 Java NIO Overview 3 Java NIO Channel 4 Java NIO Buffer 5 Java NIO Scatter / Gather 6 Java NIO Channel t...
702 0
Java项目-基于Springboot实现英语在线学习系统
本项目基本Springboot开发实现,并同时使用Springmvc+mybatis框架来进行开发实现,主要实现一个在线学习英语的基于B/S结构的学习系统。本英语学习项目是为了满足学生学习英语的需求而开发,在本系统中学生可以通过背单词,每日一句,听听力,看阅读等方式加深对英语的学习与了解。 本系统的用户角色分为前端用户和后端管理用户角色,前端用户可以在本系统中进行注册后登陆,注册后会向用户的邮箱发送一个激活账户的邮箱,用户登陆邮箱后在线激活账户方可登陆系统。登陆系统后可以在线学习英语单词 ,进行听力训练,进行在线阅读学习等操作。后台管理账户登陆系统后可以对学习单词 、书籍、用户等 信息进行相
34 0
+关注
boxti
12535
10005
文章
1326
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载