转载:Java NIO 学习笔记 - ByteBuffer

在 nio 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 nio 中的数据,都是将它放到缓冲区中。缓冲区实质上是一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不仅仅是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程。

buffer其实只是一个美化了的数组。

状态变量

跟踪数据的状态情况使buffer可以自己管理数据资源

position: 其实是指从buffer读取或写入buffer的下一个元素位置。比如,已经写入buffer 3个元素那那么position就是指向第4个位置,即position设置为3(数组从0开始计)。

limit:还有多少数据需要从buffer中取出,或还有多少空间可以放入。postition总是capacity: 表示buffer本身底层数组的容量。limit绝不能>capacity。

filp():作了两件事情:1.将limit指向现在position的位置 2.将position设置为0 (limit=position;position=0)

这个过程可以使之前buffer写入数据时改变的状态变为可以“准备读取”。因为之前写到buffer中的数据就是position 到 limit-1 两个位置之间(limit指向最后一个数据的后一个位置)。

clear():

也作了两件事:1. limit=capacity 2.position=0

这个过程可以使buffer读取数据时改变的状态改变为“清空并准备写入”。

访问方法

以下都以bytebuffer为例

get():

前三个get方法是相对读取。就是相对于位置状态来读取数据,并且会改变position位置状态。

byte get();

bytebuffer get(byte dst[]);//读取bytebuffer中数据写入 dst[]

bytebuffer get(byte dst[],int offset, int length);

该读取数据是绝对读取(一个byte),即会忽略limit和position值。并完全绕过了缓冲区的状态统计方法。

就是说不会改变buffer内部的位置状态。

byte get(int index);

put();

与get类似 前四个put方法是相对读取。即受position 以及limit影响,并且会改变 position。

bytebuffer put( byte b );

bytebuffer put( byte src[] ); //从src[]写入bytebuffer

bytebuffer put( byte src[], int offset, int length );

bytebuffer put( bytebuffer src );

最后一个是绝对写入 不会影响position等位置状态。

bytebuffer put( int index, byte b );

除了byte的读写还有其他类型的读写方法。并且他们都存在相对以及绝对两类。

操作的典型使用:

view plaincopy to clipboardprint?

while (true) {

buffer.clear(); // 准备将数据写入buffer

int r = fcin.read( buffer ); // channel读取外部系统的数据并写入 buffer

if (r==-1) {

break;

}

buffer.flip(); //准备将数据读出buffer

fcout.write( buffer ); // channel读取buffer的数据并写到相应的外部系统

}

高级应用

缓存区的分配和包装

bytebuffer.allocate(int);方法可以分配(创建)一个byte类型的buffer。

bytebuffer.wrap(byte[]);方法可以将一个已有的byte数组包装出一个新的bytebuffer对象。

后一种方式需要小心处理原来的那个byte数组。因为它可以直接访问了。

缓冲区的分片

分片就是建立“子缓冲区”。子缓冲区共享父缓冲区的一部分底层数组位置。

在某种意义上,子缓冲区就像原来的缓冲区中的一个窗口。

这样当改变子缓冲区的内容时,父缓冲区的相应位置也会被改变。

分片操作是根据当前position以及limit的值来确定的。

buffer.position( 3 );

buffer.limit( 7 );

bytebuffer slice = buffer.slice();

只读缓冲区

asreadonlybuffer()方法可以返回一个与原buffer对象一样的对象,只是新的buffer对象是只读的。

直接缓冲区

sun的定义:给定一个直接字节缓冲区,java 虚拟机将尽最大努力直接对它执行本机 i/o 操作。也就是说,它会在每一次调用底层操作系统的本机 i/o 操作之前(或之后),尝试避免将缓冲区的内容拷贝到一个中间缓冲区中(或者从一个中间缓冲区中拷贝数据)。

创建directbuffer的方式是用bytebuffer.allocatedirect( int );方法替代bytebuffer.allocate(int);

内存影射文件i/o

它读写要比其他io快很多.

他使文件或文件的一部分由内存影射。但是只有操作该部分位置的数据才是以内存方式读写的,而不是整个文件读入内存。(并且他是一个os的底层机制。由os底层异步完成内存与物理磁盘上的数据同步)

影射文件可以通过filechannel对象的map方法得到。

比如以下就是将一个文件的前1024个字节影射到内存,并创建一个mappedbytebuffer对象返回出来。mappedbytebuffer是bytebuffer的一个子类。

mappedbytebuffer mbb = fc.map( filechannel.mapmode.read_write, start, size );

参考地址:http://blog.csdn.net/wfeng007/archive/2010/02/14/5308614.aspx


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值