在NIO中,数据的读写操作始终是与缓冲区相关联的.读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入缓冲区.缓冲区是定长的,基本上它只是一个列表,它的所有元素都是基本数据类型.ByteBuffer是最常用的缓冲区,它提供了读写其他数据类型的方法,且信道的读写方法只接收ByteBuffer.因此ByteBuffer的用法是有必要牢固掌握的.

1.创建ByteBuffer
1.1 使用allocate()静态方法
    ByteBuffer buffer=ByteBuffer.allocate(256);
    以上方法将创建一个容量为256字节的ByteBuffer,如果发现创建的缓冲区容量太小,唯一的选择就是重新创建一个大小合适的缓冲区.

1.2 通过包装一个已有的数组来创建
    如下,通过包装的方法创建的缓冲区保留了被包装数组内保存的数据.
    ByteBuffer buffer=ByteBuffer.wrap(byteArray);

如果要将一个字符串存入ByteBuffer,可以如下操作:
    String sendString="你好,服务器. ";
    ByteBuffer sendBuffer=ByteBuffer.wrap(sendString.getBytes("UTF-16"));

2.回绕缓冲区
  buffer.flip();
  这个方法用来将缓冲区准备为数据传出状态,执行以上方法后,输出通道会从数据的开头而不是末尾开始.回绕保持缓冲区中的数据不变,只是准备写入而不是读取.

3.清除缓冲区
  buffer.clear();
  这个方法实际上也不会改变缓冲区的数据,而只是简单的重置了缓冲区的主要索引值.不必为了每次读写都创建新的缓冲区,那样做会降低性能.相反,要重用现在的缓冲区,在再次读取之前要清除缓冲区.

4.从套接字通道(信道)读取数据
  int bytesReaded=socketChannel.read(buffer);
  执行以上方法后,通道会从socket读取的数据填充此缓冲区,它返回成功读取并存储在缓冲区的字节数.在默认情况下,这至少会读取一个字节,或者返回-1指示数据结束.

5.向套接字通道(信道)写入数据
  socketChannel.write(buffer);
  此方法以一个ByteBuffer为参数,试图将该缓冲区中剩余的字节写入信道.

-----------------------

ByteBuffer俗称缓冲器, 是将数据移进移出通道的唯一方式,并且我们只能创建一个独立的基本类型缓冲器,或者使用“as”方法从 ByteBuffer 中获得。ByteBuffer 中存放的是字节,如果要将它们转换成字符串则需要使用 Charset , Charset 是字符编码,它提供了把字节流转换成字符串 ( 解码 ) 和将字符串转换成字节流 ( 编码) 的方法。

private byte[] getBytes (char[] chars) {//将字符转为字节(编码)
   Charset cs = Charset.forName ("UTF-8");
   CharBuffer cb = CharBuffer.allocate (chars.length);
   cb.put (chars);
   cb.flip ();
   ByteBuffer bb = cs.encode (cb)
   return bb.array();
         }

private char[] getChars (byte[] bytes) {//将字节转为字符(解码)
      Charset cs = Charset.forName ("UTF-8");
      ByteBuffer bb = ByteBuffer.allocate (bytes.length);
      bb.put (bytes);
      bb.flip ();
       CharBuffer cb = cs.decode (bb);
  
   return cb.array();
}

通道也就是FileChannel,可以由FileInputStream,FileOutputStream,RandomAccessFile三个类来产生,例如:FileChannel fc = new FileInputStream().getChannel();与通道交互的一般方式就是使用缓冲器,可以把通道比如为煤矿(数据区),而把缓冲器比如为运煤车,想要得到煤一般都通过运煤车来获取,而不是直接和煤矿取煤。用户想得到数据需要经过几个步骤:

一、用户与ByteBuffer的交互

向ByteBuffer中输入数据,有两种方式但都必须先为ByteBuffer指定容量

ByteBuffer buff = ByteBuffer.allocate(BSIZE);

a)  buff  =  ByteBuffer.wrap("askjfasjkf".getBytes())注意:wrap方法是静态函数且只能接收byte类型的数据,任何其他类型的数据想通过这种方式传递,需要进行类型的转换。

b)  buff.put();可以根据数据类型做相应调整,如buff.putChar(chars),buff.putDouble(double)等

二、FileChannel 与 ByteBuffer的交互:

缓冲器向通道输入数据

FileChannel fc = new FileInputStream().getChannel();

fc.write(buff);

fc.close();

三、 用户与ByteBuffer交互

通道向缓冲器送入数据

FileChannel fc =  new FileOutputStream().getChannel();

fc.read( buff);

fc.flip();

四、呈现给用户(三种方式)

1)String encoding = System.getProperty("file.encoding");

System.out.println("Decoded using " + encoding + ": "  + Charset.forName(encoding).decode(buff));

2)System.out.println(buff.asCharBuffer());//这种输出时,需要在输入时就进行编码getBytes("UTF-8")

3) System.out.println(buff.asCharBuffer());//通过CharBuffer向ByteBuffer输入 buff.asCharBuffer().put。

fc.rewind();

ByteBuffer用法小结的更多相关文章

  1. 转载:Hadoop排序工具用法小结

    本文转载自Silhouette的文章,原文地址:http://www.dreamingfish123.info/?p=1102 Hadoop排序工具用法小结 发表于 2014 年 8 月 25 日 由 ...

  2. [No000010]Ruby 中一些百分号(%)的用法小结

    #Ruby 中一些百分号(%)的用法小结 #这篇文章主要介绍了Ruby 中一些百分号(%)的用法小结,需要的朋友可以参考下 what_frank_said = "Hello!"#% ...

  3. C++ typedef用法小结 (※不能不看※)

    C++ typedef用法小结 (※不能不看※) 第一.四个用途 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如:char* pa, pb; // 这多数不 ...

  4. 函数fgets和fputs、fread和fwrite、fscanf和fprintf用法小结 (转)

    函数fgets和fputs.fread和fwrite.fscanf和fprintf用法小结 字符串读写函数fgets和fputs 一.读字符串函数fgets函数的功能是从指定的文件中读一个字符串到字符 ...

  5. 1:CSS中一些@规则的用法小结 2: @media用法详解

    第一篇文章:@用法小结 第二篇文章:@media用法 第一篇文章:@用法小结 这篇文章主要介绍了CSS中一些@规则的用法小结,是CSS入门学习中的基础知识,需要的朋友可以参考下     at-rule ...

  6. 英语语法最终珍藏版笔记- 21it 用法小结

    it 用法小结 it 在英语中的意思较多,用法较广,现总结如下. 一.it作句子的真正主语 1.it 指前面已经提到过的人或事物,有时指心目中的或成为问题的人或事物,作真正主语. 例如: What’s ...

  7. [转]ssh常用用法小结

    ssh常用用法小结 1.连接到远程主机: 命令格式 : ssh name@remoteserver 或者 ssh remoteserver -l name 说明:以上两种方式都可以远程登录到远程主机, ...

  8. 结构体定义 typedef struct 用法详解和用法小结

    typedef是类型定义的意思.typedef struct 是为了使用这个结构体方便.具体区别在于:若struct node {}这样来定义结构体的话.在申请node 的变量时,需要这样写,stru ...

  9. typedef用法小结

    typedef用法小结- - 注意:本文转自网络,版权归原作者所有. typedef typedef用法小结- - 这两天在看程序的时候,发现很多地方都用到typedef,在结构体定义,还有一些数组等 ...

随机推荐

  1. Unity3D脚本中文系列教程(八)

    ◆ static var matrix : Matrix4x4 描述:设置用于渲染所有gizmos的矩阵. 类方法 ◆ Static function DrawCube(center:Vector3, ...

  2. Unity3D研究院之脚本批量打包渠道包研究

    原地址:http://www.xuanyusong.com/archives/2418#comments 最近在研究Unity3D脚本批量打包,比如在Android平台下各种不同分辨率和不同内存大小的 ...

  3. Chpater 10: Sorting

    Internal Sort: Bubble  O(n2) Selection O(n2) Insertion O(n2) Shell O(nlogn) Merge O(nlogn) Heap O(nl ...

  4. POJ 1663

    #include<iostream>//cheng da cai zi using namespace std; int main() { int time; cin>>tim ...

  5. 深入浅出ES6(六):解构 Destructuring

    作者 Jason Orendorff  github主页  https://github.com/jorendorff 什么是解构赋值? 解构赋值允许你使用类似数组或对象字面量的语法将数组和对象的属性 ...

  6. DJANGO问题--Error: ‘ManyRelatedManager’ object is not iterable

    http://www.itblah.com/django-error-manyrelatedmanager-object-iterable/ Django: Error: ‘ManyRelatedMa ...

  7. form表单中的enctype属性什么意思?

    enctype就是encodetype翻译成中文就是编码类型的意思!multipart/form-data是指表单数据有多部分构成:既有文本数据,又有文件等二进制数据的意思.另外需要注意的是:默认情况 ...

  8. Openflow的转发与传统的转发区别和优势

    来源:(SDN QQ群语录20130819) http://www.sdnap.com/sdnap-post/2411.html 山东同学-菜(Q群279796875) 21:40:21我是想问,op ...

  9. lintcode 中等题:Max Points on a Line 最多有多少个点在一条直线上

    题目 最多有多少个点在一条直线上 给出二维平面上的n个点,求最多有多少点在同一条直线上. 样例 给出4个点:(1, 2), (3, 6), (0, 0), (1, 3). 一条直线上的点最多有3个. ...

  10. nginx/apache/php隐藏http头部版本信息的实现方法

    有时候我们需要隐藏我们的服务器版本信息,防止有心人士的研究,更安全,这里介绍下在nginx/apache/php中如何隐藏http头部版本信息的方法. nginx隐藏头部版本信息方法 编辑nginx. ...