ByteBuffer用法小结

在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();

时间: 2024-10-02 03:36:40

ByteBuffer用法小结的相关文章

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

C++ typedef用法小结 (※不能不看※) 第一.四个用途 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如:char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针, // 和一个字符变量:以下则可行:typedef char* PCHAR; // 一般用大写PCHAR pa, pb; // 可行,同时声明了两个指向字符变量的指针虽然:char *pa, *pb;也可行,但相对来说没有用typedef的形式直观,

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

it 用法小结 it 在英语中的意思较多,用法较广,现总结如下. 一.it作句子的真正主语 1.it 指前面已经提到过的人或事物,有时指心目中的或成为问题的人或事物,作真正主语. 例如: What’s this? -It is a sheep? 这是什么??这是一只绵羊. Who is it? -It’s me (I). 谁??是我. It’s the wind shaking the window. 是风刮得窗户响. 2.it指时间.季节.一般用在无人称动词的主语. 例如: What time

iOS开发系列之一 - UIButton 用法小结

// 初始化按钮并设置类型 UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // 能够定义的UIButton类型有以下6种: // typedef enum { // UIButtonTypeCustom = 0, 自定义风格 // UIButtonTypeRoundedRect, 圆角矩形 // UIButtonTypeDetailDisclosure, 蓝色小箭头按钮,主要做详细说明用 // UIButto

iOS开发系列之二 - UILabel 用法小结

// 初始化标签 UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 100, 300, 150)]; // 设置标签文字 label.text = @"This is a test text.This is a test text.This is a test text."; // 设置标签文字字体 // 使用系统字体 label.font = [UIFont systemFontOfSize:20]; //

jstree用法小结

jstree是一款功能强大的插件.官网地址http://www.jstree.com/ $('#jstree').jstree({ "core" : { "animation" : 0, "themes" : { "dots": true,"icons":true ,"stripes":false}, "check_callback" : true, "mu

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

typedef是类型定义的意思.typedef struct 是为了使用这个结构体方便.具体区别在于:若struct node {}这样来定义结构体的话.在申请node 的变量时,需要这样写,struct node n;若用typedef,可以这样写,typedef struct node{}NODE; .在申请变量时就可以这样写,NODE n;区别就在于使用时,是否可以省去struct这个关键字. 第三篇:struct和typedef struct 分三块来讲述:1 首先:在C中定义一个结构体

asp.net中Page.ClientScript.RegisterStartupScript用法小结(转)

//ASP.NET后台页面跳转 Page.ClientScript.RegisterStartupScript(Page.GetType(), "", "<script>if(confirm('保存成功!是否继续添加?')){location.href='ProductonAdd.aspx'}else{location.href='ProductonList.aspx'}</script>"); //后台弹出确定框 ClientScript.

Java中static、final用法小结(转)

一.final 1.final变量: 当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变.其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中.这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值. 当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的

转 C/C++基础知识:typedef用法小结

第一.四个用途 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如: char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针, // 和一个字符变量: 以下则可行: typedef char* PCHAR; // 一般用大写 PCHAR pa, pb; // 可行,同时声明了两个指向字符变量的指针 虽然: char *pa, *pb; 也可行,但相对来说没有用typedef的形式直观,尤其在需要大量指针的地方,typed