bytebuffer常用方法_bytebuffer.get

bytebuffer常用方法_bytebuffer.getByteBuffer的心得

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

NIO,数据的读写操作始终是与缓冲区相关联的(读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入缓冲区)

缓冲区是定长的,基本上它只是一个列表,它的所有元素都是基本数据类型String并未包含其中,但是String. getBytes就可以了.

 

Nio缓冲区的7种形式

ByteBuffer 

ShortBuffer 
  IntBuffer 
  CharBuffer 
  FloatBuffer 
  DoubleBuffer 
  LongBuffer 

 

 

 

     ByteBuffer是最常用的缓冲区,它提供了读写其他数据类型的方法,且信道的读写方法只接收ByteBuffer

ByteBuffer的属性中:有以下3种常见属性

m:mark:初始值为-1,标记索引地点

p:position:初始值为0,索引下标

l:limit:最好定义成bytebuffer的长度,即允许可读空间长度

c:capacity:缓冲区能容纳的数据元素的最大数量,创建之后无法被改变

总的关系m

 

 

 

1.       创建ByteBuffer
1.1
 使用allocate()静态方法

//创建一个容量为256字节的ByteBuffer,

ByteBuffer buffer=ByteBuffer.allocate(256);

        参数为ByteBuffer的长度,这个一定要在前期设计时考虑充足,不然就得重新创建

创建其他缓冲区也是这样的静态方法创建的Buffer父类引用对象 。

 

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

      // wrap(int[] array, int offset, int length)
      无论要使用的子数组的偏移量offset ,还是子数组的长度length ,使用这个方法的过程都是缓冲整个数组的过程。
      而且buffer与数组创建强耦合联系,数据改变则缓冲区值也会改变,反之亦然

 

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

        //ByteBuffer中读出String

       Charset cs = Charset.forName (“UTF-8”);

        byte[] bs = new byte[sendBuffer. limit()];

        sendBuffer.get(bs);

        String news = new String(bs, cs);

//String news = new String(sendBuffer.array(), cs);

注释里的方法也是可行,只是要注意array()方法不是将ByteBufferpositionlimit段的byte[]数组输出,而是输出缓存区所有的byte[]数组!包括limit之后的!

 

 

2.回绕缓冲区
  buffer.flip();

byte[] data = new byte[buffer.remaining()];

    buffer.get(data);      

//  session开始写入数据

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

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

以下为常用方式
4.
从套接字通道(信道)读取数据
   SocketChannel
采用的是非阻塞异步读取流数据,在读取的时候,通常是

ByteBuffer.clear();

SocketChannel.read(ByteBuffer);

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

  如果流中有数据,就会把数据从position开始读到ByteBuffer中,在读取之前ByteBufferclear操作会把position置为0,limit置为capability,也就是相当于清空了之前的内容,但是ByteBuffer中数组的内容在read之前是没有改变的.

read之后,通常就是开始从ByteBuffer中提取读到的数据,如果你的数据是以自己定义的数据包的格式进行发送的,那你还需要判断是否读到了数据包的结尾,因为对流数据本身来说是没有结尾这一说的。在提取数据之前,要先把position放到开始读取时的位置,limit放到当前位置,所以要flip一下,表示从positionlimit的位置都是需要的数据。

ByteBuffer.flip();

while(ByteBuffer.hasRemaining()){

  byte c=ByteBuffer.get();

  if (b == PACKAGE_END) {

      //you can return the package here

  }else{

      //you can append the byte here.like StringBuilder.append().

  }

}

这样以来也存在一个问题,当一次读到的ByteBuffer不包含完整的数据包或者包含多个数据包.那么就需要在下一次继续把这些包分拆出来.那么在读取数据的代码处就可以改为,这样就把之前读取到的未完整的包保留了下来:

if(!ByteBuffer.hasRemaining){

    ByteBuffer.clear();

    SocketChannel.read(ByteBuffer);

}

另外一个可能会用到的操作就是ByteBuffer.rewind(),他会把position置为0limit保持不变,可以用于重复读取一段数据.

 

 

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

 

6.ByteBuffer与字符的互转

   

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

 

7. put()方法远比想象的强大

    buff.put();可以根据数据类型做相应调整

    比如buff.putChar(chars),buff.putDouble(double)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/186833.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 概率公理化定义的理解

    概率公理化定义的理解由于自己研究生方向为计算机视觉,需要用到许多概率论方面相关的知识,出来混早晚是要还滴!由于本科概率论课不太适应老师的语调,大多数课都睡过去了。。。就连最基本的概率的公理化定义,都快大学毕业了,都一直没有理解,真是囧!赶紧恶补了下概率论,感觉对公理化定义有了一点新的认识,一方面写出来加深自己的记忆,一方面分享出来,供有同样疑问的同学看看,水平有限,如有错误也在所难免,恳请大家指出,然后我进行改正

    2022年8月31日
    4
  • 代理模式(proxy)

    前言 代理模式是一个大类,而且会经常用到,它包含了远程代理,虚拟代理,防火墙代理等,当然还有动态代理了,学过spring的人应该不陌生。 各种代理模式样式差别很大,不容易从程序上辨认,但是可以从功能上认出来,今天我就举个例子聊聊代理模式最基本的样子,从例子中认识代理模式。 举例为静态代理的基本应用,稍后再介绍代理模式的一些特点。  情境引入      本次我们以滴滴为例…

    2022年4月4日
    44
  • 快递查询API接口集成,有需要的可以直接用

    快递查询API接口集成,有需要的可以直接用

    2021年10月26日
    46
  • linux中kill命令详解_linux kill函数

    linux中kill命令详解_linux kill函数linuxkill命令详解一、命令格式:kill[参数][进程号]二、命令功能:发送指定的信号到相应进程。不指定型号将发送SIGTERM(15)终止指定进程。如果任无法终止该程序可用“-KILL”参数,其发送的信号为SIGKILL(9),将强制结束进程,使用ps命令或者jobs命令可以查看进程号。root用户将影响用户的进程,非root用户只能影响自己的进程。三、命令参数:-l信号,若果不加信号的编号参数,则使用“-l”参数会列出全部的信号名称-a当处理当前进程时,不

    2025年7月1日
    3
  • 学习笔记 | 非负矩阵分解(NMF)浅析

    学习笔记 | 非负矩阵分解(NMF)浅析这篇博客简单地介绍非负矩阵分解(NMF),包括背景说明、NMF原理简介、代码分享以及NMF在一个趣味问题中的解决方案。

    2022年6月26日
    31
  • 2017年北理工研究生复试总结「建议收藏」

    2017年北理工研究生复试总结「建议收藏」就在昨天还为自己在专家面试环节答题答得非常糟糕的事情感到懊恼不已,今天进入官网一看,我的天,竟然过了,复试成绩竟然77分,仅比第一名差2分。

    2022年4月27日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号