`

关于ByteBuffer使用解释

    博客分类:
  • nio
 
阅读更多

之前看过相关的ByteBuffer的使用,但是问题是那时还年轻,所以现在有点老了,因此,忘记了,所以决心看源代码了解一番----故作此篇文章。

 

查看ByteBuffer的API,看的我是一头雾水,搞不清什么mark、position、limit、flip、reset几个的用法,先看下面的例子:

Java代码  收藏代码
  1.      String str = "helloWorld";  
  2.         ByteBuffer buff  = ByteBuffer.wrap(str.getBytes());  
  3.         System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());  
  4.         //读取两个字节  
  5.         buff.get();  
  6.         buff.get();  
  7.         System.out.println("position:"+ buff.get(buff.position())+"\t limit:"+buff.limit());  
  8.         buff.mark();  
  9.         System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());  
  10.         buff.flip();  
  11.         System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());<span style="white-space: pre;">    </span>  
Java代码  收藏代码
  1. <pre name="code" class="java">输出结果:  
  2. position:0  limit:10  
  3. position:2  limit:10  
  4. position:2  limit:10  
  5. position:0  limit:2  
  6. </pre>  
  7.    
  我们以每位开发人员熟悉的”helloworld“,用ByteBuffer将字符串包装,由于ByteBuffer是一个抽象类,通过wrap包装的对象将实际返回的是一个HeapByteBuffer对象。由此可知HeapByteBuffer是ByteBuffer的子类,同样的ByteBuffer又是Buffer抽象类的子类。以上提到的mark、position、limit、flip、reset都是出自于Buffer这个抽象类。
下面我们来解析几个方法的,当我们调用了wrap方法后Buffer中初始化的结构是:
注释:
m:mark;
p:position;
L:limit;
 
   初始情况下mark是指向第一个元素之前的的即-1,postion为指向第一个元素为0.而Limit是被赋值为byte[]的长度。
因此这就是打印结果的第一行。
m     p               L
-1 0 1 2 3 4 5 6 7 8 9  
  H E L L O W O R L D  
   当我们连续调用两次get()方法获得两个个字节,每次调用都会触发position++操作,那么此时position就会移动到index = 2的的地方,而这个时候Limit和mark是不会发生变化的。如果将读取的两个字节打印会是H和E,因此执行结果第二行会有position:2  limit:10结果.
      m、p               L
-1 0 1 2 3 4 5 6 7 8 9  
  H E L L O W O R L D  
     读取完毕后我们使用mark,这个时候mark会从-1移动到2和position指向同一个元素,可以看见Limit是不会发生改变的。
m p   L                
-1 0 1 2 3 4 5 6 7 8 9  
  H E L L O W O R L D  
    使用了mark标记的当前的position后,如果们调用flip,这个时候Limit就会指向position的位置,并将mark和position还原为初始值。这样就知道了limit当前的就为2,什么意思呢?就是说当前可以读的字节数是2。
我们可以尝试一下如下代码:
 
Java代码  收藏代码
  1. System.out.println((char)buff.get()+""+(char)buff.get());  
    输出结果:he
    貌似这也没什么稀奇的,如果你在代码换成
 
Java代码  收藏代码
  1. // System.out.println((char)buff.get()+""+(char)buff.get()  
  2.    System.out.println((char)buff.get()+""+(char)buff.get()+""+(char)buff.get());  
Java代码  收藏代码
  1. 输出结果:<pre name="code" class="java">position:0    limit:10  
  2. Exception in thread "main" java.nio.BufferUnderflowException  
  3.     at java.nio.Buffer.nextGetIndex(Buffer.java:474)  
  4.     at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:117)  
  5.     at com.taobao.moxing.notify.Main.main(Main.java:33)position:2    limit:10  
  6. position:2   limit:10  
  7. position:0   limit:2  
  8. </pre>  
   为什么会抛异常呢?原因是limit的含义就想一个窗口,你当前能读到的数据就是当前窗口限制的(本例中即为2),如果这个窗口之外的所有元素都是不可读的。至此我想你和我就应该明白这几个参数的含义了吧。
    而至于reset方法,它是将当前的position设置为0,
     rewind是将mark重置为-1,position重置为0;
     clear方法是真正的重置,将mark=-1,position=0,limit=capacity(即当前buffer的容量)
分享到:
评论

相关推荐

    字节流字符流

    在"FileTest"这个文件中,可能包含了一些关于字节流和字符流使用的示例代码或测试用例。通过阅读和理解这些代码,我们可以深入学习如何在Java中运用字节流和字符流进行文件操作,以及如何在需要时进行两者之间的转换...

    Java.NIO资源下载资源下载

    根据提供的文件信息,我们可以提取并总结出关于Java NIO(New Input/Output)的重要知识点。 ### Java NIO 概述 Java NIO 是 Java 平台的一个重要特性,首次出现在 Java 1.4 版本中。它为 Java 开发者提供了一套...

    java关于BMP位图文件解析的分析与实现[源码][附图]

    通过阅读提供的博客文章(),你可以找到更详细的解释和完整的源代码,这将帮助你更好地理解BMP文件解析的过程,并可能包含处理不同情况的额外功能。此外,还可以参考Java的`java.awt.image`包中的其他类,例如`...

    网络与nio

    3. **ByteBuffer**:解释ByteBuffer的使用,如何分配、读写数据以及切换读写模式。 4. **选择器Selector**:阐述Selector的工作原理,如何注册Channel、选择就绪事件以及进行多路复用。 5. **服务器端编程**:展示...

    netty-api-4.1中文.rar

    在 "netty-api-4.1中文.CHM" 文件中,你将找到关于 Channel、Pipeline、Handler、EventLoopGroup 等核心概念的详细解释,以及如何配置和使用 Netty 来创建服务器和客户端的示例。此外,文档还会涵盖错误处理、性能...

    Android开发问题集锦第一期

    - 当你需要准备一个新的`ByteBuffer`来写入数据时,应该使用`clear()`。 - 如果你想重新读取`ByteBuffer`中的数据,但不希望丢失已有的数据,可以使用`rewind()`。 - 而当你完成了写操作,并且想要切换到读模式时,...

    MINA2官方教程翻译

    - MINA2中,原来的`ByteBuffer`被重命名为`IoBuffer`,以避免与Java NIO的`ByteBuffer`混淆,同时使得类名更具描述性。 - 废弃了Buffer池,并默认使用`IoBuffer.allocate(int)`分配堆缓冲区。这意味着不再需要`...

    Java NIO原理分析及代码实例

    首先,我们来详细解释一下这些核心概念: 1. **通道(Channel)**:通道类似于流,但它们是双向的,可以用于读取和写入数据。Java NIO中的通道类有FileChannel、SocketChannel、ServerSocketChannel等。通道可以从...

    JAVA BMP解码 超详细解释

    例如,`BufferedImage`类可以用来表示图像,`FileInputStream`用于读取文件,`DataInputStream`或`ByteBuffer`用于读取字节数据。 博客链接中的资源(ver1)可能包含一个示例程序,演示了如何使用JAVA进行BMP解码的...

    JAVA 转换字符编码工具

    博文链接提到的是博主SammyFun在ITEYE上分享的一个关于Java字符编码转换的实践案例,可能包括自定义工具类或者方法,以简化编码转换的流程,提高代码的可读性和可维护性。由于没有具体的博文内容,无法提供更详细的...

    netty api文档

    在`netty-4.1.0.CHM`这个文档中,你可以找到关于Netty 4.1.0版本的详细API说明,涵盖了所有核心组件、接口和类的使用方法,包括Channel、ByteBuf、EventLoopGroup、Pipeline、Handler等关键概念的解释,以及各种协议...

    Android开发问题集锦第一期.pdf

    【Android开发问题集锦第一期】包含了多个关于Android开发中常见问题的解答,这些问题涵盖了图像处理、内存管理、Java特性的支持以及系统组件的使用等多个方面。以下是对这些问题的详细解释: 1. **Bitmap如何保存...

    读取txt单字节数据格式

    在博客“百度CSDN CRACENT”中,可能会有更深入的示例代码和详细的解释,帮助读者理解如何在实际项目中应用这些步骤。通过学习这个主题,开发者可以更好地处理低级别的数据操作,这对于处理特定格式的文件或者需要...

    利用socket实现双机通信.

    - 注意,为了提高效率和避免一次性加载大文件到内存,可以使用缓冲区(如ByteBuffer)分块传输。 5. **实验报告**: - 实验报告应包含实验目的、环境配置、步骤描述、问题分析和改进方案等部分。在描述实现过程时...

    jni 开发 帮助文档 api 适合安卓/Android(中文)

    本帮助文档专注于在Android环境下使用JNI进行开发,提供了全面的API指南,全中文解释,便于国内开发者理解和应用。 1. JNI基础: - JNI头文件:开发JNI时,需要包含`&lt;jni.h&gt;`头文件,它定义了所有与JNI相关的类型...

    java-16进制4字节转Float

    以下是关于这个主题的详细解释。 首先,16进制是一种数字表示方式,每4个字符代表一个字节(8位)。浮点数在计算机内部通常是用二进制的格式存储的,具体分为两部分:符号位、指数部分和尾数部分。在Java中,浮点数...

    HDFS 的读写数据流程:

    5. 建立Block传输通道:客户端请求建立Block传输通道到DataNode,使用bytebuffer的形式请求建立通道。 6. 请求数据传输:客户端请求数据传输到DataNode,DataNode将数据写入磁盘。 7. 传输数据packet(chunk512+...

    DougLeaNio.pdf

    - 讲解了如何使用`java.nio`包中的类和方法,如`Selector`、`Channel`、`ByteBuffer`等,以及它们在实现高性能网络通信中的作用。 从以上提到的要点可以看出,Doug Lea在Java NIO方面的讲解非常全面,覆盖了从基础...

    Android开发问题集锦第一期[归纳].pdf

    Android 开发问题集锦第一期涵盖了多个常见的Android开发难题,以下是对这些问题的详细解释: 问题一:Bitmap如何保存成为一个bmp文件 在Android中,Bitmap对象默认的压缩格式仅支持PNG和JPEG。要将Bitmap保存为BMP...

Global site tag (gtag.js) - Google Analytics