在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. 原 Linux搭建SVN 服务器

    原 Linux搭建SVN 服务器 发表于1年前(2014-08-05 17:55)   阅读(12257) | 评论(3) 31人收藏此文章, 我要收藏 赞3 摘要 Linux搭建SVN 服务器 目录 ...

  2. kill 非法用户

    主要涉及到的相关命令如:who/w/ps/kill/pkill/killall查看当前登录用户:[root@localhost ~]# whoroot     pts/1        2010-08 ...

  3. APAC Practice

    2016 round A A. Googol String small && large LL a[]; int dfs(LL pos, int id, bool f) { || po ...

  4. [主席树]ZOJ2112 && BZOJ1901 Dynamic Rankings

    题意:n个数,q个询问 (n<=50000, q<=10000) Q x y z 代表询问[x, y]区间里的第z小的数 C x y    代表将(从左往右数)第x个数变成y 上篇介绍了在 ...

  5. spring 与 CXF 整合 webservice 出现error “Unable to locate Spring NamespaceHandler for XML schema namespace” 总结

    我试了多个版本的spring 发现 出现error : Unable to locate Spring NamespaceHandler for XML schema namespace 并非都是sp ...

  6. C++客户端程序(socket)

    // MyClient.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h"#include "stdio.h"#include ...

  7. ServletRequest中getReader()和getInputStream()只能调用一次的解决办法

    转载:http://blog.sina.com.cn/s/blog_870cd7b90101fg58.html 最近使用spring mvc做项目,数据格式是json,有一个功能是实现记录请求的参数, ...

  8. iOS视频录制、压缩导出、取帧

    概述 花了点时间研究了一下常用的视频获取.录制.压缩.取帧图功能,分享给大家了!相信阅读完本篇文章,会对你有很大的帮助的! 本篇文章研究几下以个功能: 视频录制 从相册选择视频 保持视频到相册 获取视 ...

  9. PowerDesigner的样式设置

    原文:PowerDesigner的样式设置 PD提供了强大的配置功能,可以对生成的数据库对象命名.数据模型的展现进行设置.这里首先讲下样式的设置. 颜色和字体设置 1.单独设置某个对象的颜色和字体 1 ...

  10. zenmap 的扫描方式

    第一种:Intense scan (nmap -T4 -A -v) 一般来说,Intense scan可以满足一般扫描 -T4 加快执行速度 -A 操作系统及版本探测 -v 显示详细的输出 第二种:I ...