原文地址:http://tutorials.jenkov.com/java-nio/buffers.html

JAVA NIO 是在和channel交互的时候使用的。正如你所知道的,数据是从channel中读入到buffer,从buffer中写入到channel中的。

buffer本质上是一块你可以写入然后读出的一块内存。这个内存块被封装在NIO的buffer对象中,它提供了一系列方法,使得我们可以很轻松的操作这个内存块。

Buffer基本的使用

  使用buffer读写数据至少有一下四步:

  1.   写入数据到buffer中。
  2.   调用buffer.flip()。
  3.   从buffer中读出数据。
  4.   调用buffer.clear()或者buffer.compact()。

  当你写入数据的时候,buffer会跟踪你写入了多少数据。当你需要读取数据的时候,你可以通过调用flip()方法将写入模式转换为读取模式。在读取模式中,你可以从buffer中读取所有写入的数据。

  当你读取完所有的数据的时候,你需要清除buffer中的数据,使得buffer可以再次被写入。有两种方法可以清除:调用clear()或者compact()。clear()方法清除整个buffer,而compact()方法只会清除已经读取的数据,未读取的数据则会移动到buffer的开始处,然后在未读数据的后面再开始写入。

  下面是一个简单的buffer的例子,写入,转换模式,读取,清除。

 RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel(); //create buffer with capacity of 48 bytes
ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) { buf.flip(); //make buffer ready for read while(buf.hasRemaining()){
System.out.print((char) buf.get()); // read 1 byte at a time
} buf.clear(); //make buffer ready for writing
bytesRead = inChannel.read(buf);
}
aFile.close();

Buffer Capacity,Position,Limit

  JAVA NIO 是在和channel交互的时候使用的。正如你所知道的,数据是从channel中读入到buffer,从buffer中写入到channel中的。

buffer本质上是一块你可以写入然后读出的一块内存。这个内存块被封装在NIO的buffer对象中,它提供了一系列方法,使得我们可以很轻松的操作这个内存块。

  为了理解buffer是如何工作的,有三个buffer的属性你必须熟悉。

  • capacity
  • position
  • limit

  position和limit的意义依赖于buffer的读写模式,而capacity则不管什么模式都是一样的。下图可以解释position,limit,capacity的区别。

Capacity

  作为一个内存块,buffer有一个固定的大小,同样也叫“capacity”。你只能写入capacity大小的bytes,long,chars等到buffer中。一旦buffer被写满了,在你写入更多的数据之前你需要清空它(读取或者clear)。

Position

  当你写入数据的时候,你同时也知道一个确切的位置。初始的时候,position的值是0,当一个byte,long等写入buffer的时候,position将会指向下一个待写入的空间。position的最大值是capacity - 1.

  当你读取数据的时候,同样是从一个给定的位置开始的。当你将buffer从写入模式转换到读取模式的时候,position重置为0,你从position的位置读取数据,然后position指向下一个读取的空间。

Limit

  在写模式下,limit表示你最多可以向buffer中写入多少数据。写模式下limit等于capacity。

  当把buffer转换到读模式下时,limit意味着你可以读取多少数据。因此当将buffer转换到读模式的时候,limit等于写模式下的写入到的position。换句话说,你写入多少数据就可以读取多少数据。

Buffer types

Java NIO 实现了一下的一些Buffer类型。

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

  正如你所知,java nio 的类型代表这不同的数据类型。换句话说,你可以通过使用char,short,int,long,float 或 double类型来操作缓冲区中的字节。

  MappedByteBuffer有一点特殊,我们将会在它所在的章节进行介绍。

分配Buffer

  在得到一个buffer之前,首先要为他分配空间。每一个buffer的类都有一个 allocate()的方法可以做这件事。下面一个例子表示给一个ByteBuffer分配一个48字节的空间。

ByteBuffer buf = ByteBuffer.allocate(48);

下面一个例子时表示给一个CharBuffer分配一个1024字符的空间。

CharBuffer buf = CharBuffer.allocate(1024);

向buffer中写入数据

  有两种方法可以向buffer中写入数据:

  1.   从channel写入到buffer
  2.   通过使用buffer的put()方法

下面一个例子表示从channel写入到buffer。

int bytesRead = inChannel.read(buf); //read into buffer.

下面一个例子表示使用buffer的put()函数写入数据

buf.put(127);  

  put()函数的重载的方法有很多个,因此有多种写入buffer的方式。例如:写入到一个具体的位置,或者是写入一个字节数组。更多详情请参照JDK doc。

flip()

  flip()函数是将buffer的模式从写转换为读,调用flip()使得position的值设置为0,limit的值设置为刚刚position的值。

  换句话说,position现在标志读的位置,limit标志有多少bytes,chars等写入到了buffer中,即有多少可读。

从Buffer中读数据

  从buffer中读数据也有两种方式:

  1、从buffer中读数据到channel中。

  2、使用buffer的get()函数。

  下面是一个从buffer读数据到写入到channel的例子。

int bytesWritten = inChannel.write(buf);

  下面是buffer用自身的get()函数的例子。

byte aByte = buf.get();    

  get()函数的重载的方法有很多个,因此有多种读取buffer数据的方式。例如:从一个具体的位置读取数据,或者是读取数据到一个字节数组。更多详情请参照JDK doc。

rewind ()

  rewind()函数将position设置为0,因此你可以重读刚刚读取的数据。limit仍然不变,以此仍然可以标志有多少读。

clear() 和 compact()

  一旦你从buffer中读完了数据就要将buffer重新标记为可写。可以使用clear()或者compact()来完成。

  如果使用clear(),那么position重新设置为0,limit设置为capacity。换句话说buffer被清除了。在buffer中的数据没有被清除。只有标记才能告诉你buffer中哪里可以写。

  如果有未读的数据,调用clear()的话buffer将会把他们忽略。意味着不管有多少标记告诉你还有数据未读,你也不可能再读取这些数据了。

  如果仍然有些数据未读,而且你现在必须做一些写的操作,那么就调用compact()方法而不是clear()。

  compact()会复制所有未读的数据到buffer的开始处。然后它将position设置为最后一个未读元素的右边的第一个位置。limit则和clear()的操作一致,仍然设置为capacity。现在buffer已经可以写了,而且你也不会覆盖为读的数据。

mark()和reset()

  你可以调用mark()方法标记一个位置,然后你可以调用reset()方法返回刚刚你标记的位置。下面是一个简单的例子。

buffer.mark();

//call buffer.get() a couple of times, e.g. during parsing.

buffer.reset();  //set position back to mark.   

equals() 和 compareTo()

  可以使用equals() 和compareTo()来比较两个buffer的大小。

 equals()

  两个buffer相等的条件

  1.     相同的类型(byte,char等)
  2.     buffer中有相同的剩余空间。
  3.     所有剩余的bytes,chars等相等。

  正如你所见到的,equals()只是比较buffer的一部分,而不是他的全部。事实上,它只是比较buffer中剩余的部分。

 compareTo()

  compareTo()方法比较两个buffer中剩余的元素。一个buffer比另一个buffer小的条件是:

  第一个元素比它在另一个buffer中的相同位置的值小。

  第一个buffer比第二个buffer的长度小,并且第一个buffer中的元素与之对应的第二个buffer的元素都相等。

[翻译] java NIO Buffer的更多相关文章

  1. Java NIO Buffer(netty源码死磕1.2)

    [基础篇]netty源码死磕1.2:  NIO Buffer 1. Java NIO Buffer Buffer是一个抽象类,位于java.nio包中,主要用作缓冲区.Buffer缓冲区本质上是一块可 ...

  2. (二:NIO系列) Java NIO Buffer

    出处:Java NIO Buffer Buffer是一个抽象类,位于java.nio包中,主要用作缓冲区.Buffer缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...

  3. java.nio.Buffer 中的 flip()方法

    在Java NIO编程中,对缓冲区操作常常需要使用  java.nio.Buffer中的 flip()方法. Buffer 中的 flip() 方法涉及到 Buffer 中的capacity.posi ...

  4. [翻译] java NIO Channel

    原文地址:http://tutorials.jenkov.com/java-nio/channels.html JAVA NIO channels和流的概念很像,下面是他们的一些区别: 你可以对cha ...

  5. [翻译] java NIO 教程---介绍

    原文地址:http://tutorials.jenkov.com/java-nio/index.html Java NIO(new IO)是从java1.4之后的对IO API的另一种选择,即对标准j ...

  6. Java NIO Buffer缓冲区

    原文链接:http://tutorials.jenkov.com/java-nio/buffers.html Java NIO Buffers用于和NIO Channel交互.正如你已经知道的,我们从 ...

  7. java NIO Buffer 详解(1)

    1.java.io  最为核心的概念是流(stream),面向流的编程,要么输入流要么输出流,二者不可兼具: 2.java.nio 中拥有3个核心概念: Selector Channel, Buffe ...

  8. Java NIO —— Buffer(缓冲区)

    Buffer是一个抽象类,位于java.nio包中,主要用作缓冲区.注意:Buffer是非线程安全类. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO Buffer ...

  9. Java NIO Buffer说明

    Buffer 有3个重要的参数:位置(position).容量(capactiy).上限(limit) 位置(position): 写:当前缓冲区的位置,将从position的下一个位置写数据. 读: ...

随机推荐

  1. Code[VS]1021 玛丽卡题解

    Code[VS]1021 玛丽卡题解 SPFA Algorithm 题目传送门:http://codevs.cn/problem/1021/ 题目描述 Description 麦克找了个新女朋友,玛丽 ...

  2. nodeJS中exports和mopdule.exports的区别

    每一个node.js执行文件,都自动创建一个module对象,同时,module对象会创建一个叫exports的属性,初始化的值是 {} module.exports = {}; Node.js为了方 ...

  3. nginx“虚拟目录”不支持php的解决办法

    这几天在配置Nginx,PHP用FastCGI,想装一个phpMyAdmin管理数据库,phpMyAdmin不想放在网站根目录 下,这样不容易和网站应用混在一起,这样phpMyAdmin的目录就放在别 ...

  4. Linux_JDK安装

    一.下载linux版本的jdk压缩包(这里安装jdk1.7版本,子版本随意,选择*.tar.gz文件下载) 下载目录:http://www.oracle.com/technetwork/java/ja ...

  5. HDU 2955

    Robberies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  6. Daily Scrum 10.24

    昨天我们的工作已经全面开始了,本来想等今天(25号)看那个燃尽图和燃速图能不能出来,结果还是没有,就先把我们的Task统计贴上来吧. 今天的Task统计: 至于燃尽图和燃速图的问题已经发老师邮件提问了 ...

  7. 记录下ECharts的一些功能

    用到ECharts记录下一些功能免得以后找文档找不到. 这个博客对ECharts讲解很全面 http://www.stepday.com/my.stepday/?echarts // 使用 requi ...

  8. nyoj-204

    描述国王有一个魔镜,可以把任何接触镜面的东西变成原来的两倍——只是,因为是镜子嘛,增加的那部分是反的. 比如一条项链,我们用AB来表示,不同的字母表示不同颜色的珍珠.如果把B端接触镜面的话,魔镜会把这 ...

  9. Web前端开发基础 第四课(认识CSS样式)

    CSS代码语法 css 样式由选择符和声明组成,而声明又由属性和值组成,如下图所示: 选择符:又称选择器,指明网页中要应用样式规则的元素,如本例中是网页中所有的段(p)的文字将变成蓝色,而其他的元素( ...

  10. 使用dd制作文件夹的img

    du -sh originfile //先看看需要制作的源文件夹大小,假如15M dd if=/dev/zero of=new_img.img bs=1024 count=20000 //生成20M的 ...