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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • integer类型比较大小_pow的值的数据类型

    integer类型比较大小_pow的值的数据类型IntegerTypes(ExactValue精确值)-INTEGER,INT,SMALLINT,TINYINT,MEDIUMINT,BIGINTMySQL支持SQL标准整数类型INTEGER(或INT)和SMALLINT。作为标准的扩展,MySQL还支持整数类型TINYINT、MEDIUMINT和BIGINT。下表显示了每个整数类型所需的存储和范围。.MySQL支…

    2022年9月7日
    0
  • phpstorm 常用快捷键

    phpstorm 常用快捷键

    2022年3月2日
    70
  • java文档注释报错,java文档注释主要使用方法「建议收藏」

    java文档注释报错,java文档注释主要使用方法「建议收藏」一、java包含哪些注释1.//用于单行注释。2./*…*/用于多行注释,从/*开始,到*/结束,不能嵌套。3./**…*/则是为支持jdk工具javadoc.exe而特有的注释语句。这个也就是我们所知的文档注释在命名控制台:使用命令行在目标文件所在目录输入javadoc+文件名.java。二、文档注释的关键名词/**标记用于…

    2022年10月31日
    0
  • vue的$attrs_vue获取list集合中的对象

    vue的$attrs_vue获取list集合中的对象​说明本文用示例介绍Vue的$attrs和$listener的用法官网API—Vue.js$attrs和$listeners介绍Vue2.4中,引入了attrs和listeners,新增了inheritAttrs选项。$attrs:包含了父作用域中没有被prop接收的所有属性(不包含class和style属性)。可以通过v-bind=”$attrs”直接将这些属性传入内部组件。$

    2022年8月31日
    3
  • quotename()函数 

    quotename()函数 请教quotename函数的理解,我已经看了很多帮助,储如以下示例 QUOTENAME(Transact-SQL)返回带有分隔符的Unicode字符串,分隔符的加入可使输入的字符串成为有效的MicrosoftSQLServer2005分隔标识符。Transact-SQL语法约定语法QUOTENAME(‘character_string'[,’q…

    2022年7月25日
    6
  • serialVersionUID作用

    serialVersionUID作用

    2021年12月8日
    48

发表回复

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

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