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)

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Binary Exponential Backoff

    Binary Exponential Backoff一、CSMA/CD过程      CSMA/CD就像在没有主持人的座谈会中,所有的参加者都通过一个共同的媒介(空气)来相互交谈。每个参加者在讲话前,都礼貌地等待别人把话讲完。如果两个客人同时开始讲话,那么他们都停下来,分别随机等待一段时间再开始讲话。这时,如果两个参加者等待的时间不同,冲突就不会出现。如果传输失败超过一次,将采用退避指数增长时间的方法(退避的时间通过截断二进制

  • 互斥锁设计,有效的避免死锁

    互斥锁设计,有效的避免死锁

  • Python源代码_源代码版权和软件著作权

    Python源代码_源代码版权和软件著作权一个小需求:在申请软件著作权的时候,需要提交一页50行,总共60页的源代码。但是设计的项目保存在多级的目录下,不想一个一个复制,遂通过python,os模块获得全部目录的文件,re正则化过滤无效源代码,然后基于docx模块写入到word中。涉及的模块有os,docx,re同学们要自行下载上述的模块,使用pipinstallXXX就可以的。。python大法好呀那我们就分为2个大的…

  • Java基础语法(五)运算符的那些事

    Java基础语法(五)运算符的那些事

  • 记录Depix工具的使用

    记录Depix工具的使用这个月初有一个挺让人振奋的消息,说是出了一款开源去“马赛克“工具,三天就收获了3k+star,现在star数已经达到了13.7k了,项目地址:https://github.com/beurtschipper/Depix。我是没有这种世俗的欲望的,所以当时就没关注,直到昨天”纵横杯”网络安全竞赛Misc中专门出了一个马赛克的题,就给出了下面这张图片师傅们调侃说近视眼摘下眼镜离远一点就能看清楚了,我试了一下只能看出轮廓,但是还是看不清,这就需要用到Depix这个神奇的工具了。我这里是在windows系

  • 闪讯pppoe拨号模块损坏118_创翼pppoe拨号模块损坏

    闪讯pppoe拨号模块损坏118_创翼pppoe拨号模块损坏创翼错误118pppope拨号模块损坏.1809版本、创翼的bug一、新建一个.txt文件二、复制下面代码到.txt文件里并保存WindowsRegistryEditorVersion5.00[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog]”ServiceDll”=hex(2):25,00,…

发表回复

您的电子邮箱地址不会被公开。

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