之前看过相关的ByteBuffer的使用,但是问题是那时还年轻,所以现在有点老了,因此,忘记了,所以决心看源代码了解一番----故作此篇文章。
查看ByteBuffer的API,看的我是一头雾水,搞不清什么mark、position、limit、flip、reset几个的用法,先看下面的例子:
String str = "helloWorld";
ByteBuffer buff = ByteBuffer.wrap(str.getBytes());
System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());
//读取两个字节
buff.get();
buff.get();
System.out.println("position:"+ buff.get(buff.position())+"\t limit:"+buff.limit());
buff.mark();
System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());
buff.flip();
System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());
输出结果:
position:0 limit:10
position:2 limit:10
position:2 limit:10
position:0 limit:2
我们以每位开发人员熟悉的”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。
我们可以尝试一下如下代码:
System.out.println((char)buff.get()+""+(char)buff.get());
输出结果:he
貌似这也没什么稀奇的,如果你在代码换成
// System.out.println((char)buff.get()+""+(char)buff.get()
System.out.println((char)buff.get()+""+(char)buff.get()+""+(char)buff.get());
输出结果:position:0 limit:10
Exception in thread "main" java.nio.BufferUnderflowException
at java.nio.Buffer.nextGetIndex(Buffer.java:474)
at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:117)
at com.taobao.moxing.notify.Main.main(Main.java:33)position:2 limit:10
position:2 limit:10
position:0 limit:2
为什么会抛异常呢?原因是limit的含义就想一个窗口,你当前能读到的数据就是当前窗口限制的(本例中即为2),如果这个窗口之外的所有元素都是不可读的。至此我想你和我就应该明白这几个参数的含义了吧。
而至于reset方法,它是将当前的position设置为0,
rewind是将mark重置为-1,position重置为0;
clear方法是真正的重置,将mark=-1,position=0,limit=capacity(即当前buffer的容量)
分享到:
相关推荐
在"FileTest"这个文件中,可能包含了一些关于字节流和字符流使用的示例代码或测试用例。通过阅读和理解这些代码,我们可以深入学习如何在Java中运用字节流和字符流进行文件操作,以及如何在需要时进行两者之间的转换...
根据提供的文件信息,我们可以提取并总结出关于Java NIO(New Input/Output)的重要知识点。 ### Java NIO 概述 Java NIO 是 Java 平台的一个重要特性,首次出现在 Java 1.4 版本中。它为 Java 开发者提供了一套...
通过阅读提供的博客文章(),你可以找到更详细的解释和完整的源代码,这将帮助你更好地理解BMP文件解析的过程,并可能包含处理不同情况的额外功能。此外,还可以参考Java的`java.awt.image`包中的其他类,例如`...
3. **ByteBuffer**:解释ByteBuffer的使用,如何分配、读写数据以及切换读写模式。 4. **选择器Selector**:阐述Selector的工作原理,如何注册Channel、选择就绪事件以及进行多路复用。 5. **服务器端编程**:展示...
在 "netty-api-4.1中文.CHM" 文件中,你将找到关于 Channel、Pipeline、Handler、EventLoopGroup 等核心概念的详细解释,以及如何配置和使用 Netty 来创建服务器和客户端的示例。此外,文档还会涵盖错误处理、性能...
- 当你需要准备一个新的`ByteBuffer`来写入数据时,应该使用`clear()`。 - 如果你想重新读取`ByteBuffer`中的数据,但不希望丢失已有的数据,可以使用`rewind()`。 - 而当你完成了写操作,并且想要切换到读模式时,...
- MINA2中,原来的`ByteBuffer`被重命名为`IoBuffer`,以避免与Java NIO的`ByteBuffer`混淆,同时使得类名更具描述性。 - 废弃了Buffer池,并默认使用`IoBuffer.allocate(int)`分配堆缓冲区。这意味着不再需要`...
首先,我们来详细解释一下这些核心概念: 1. **通道(Channel)**:通道类似于流,但它们是双向的,可以用于读取和写入数据。Java NIO中的通道类有FileChannel、SocketChannel、ServerSocketChannel等。通道可以从...
例如,`BufferedImage`类可以用来表示图像,`FileInputStream`用于读取文件,`DataInputStream`或`ByteBuffer`用于读取字节数据。 博客链接中的资源(ver1)可能包含一个示例程序,演示了如何使用JAVA进行BMP解码的...
博文链接提到的是博主SammyFun在ITEYE上分享的一个关于Java字符编码转换的实践案例,可能包括自定义工具类或者方法,以简化编码转换的流程,提高代码的可读性和可维护性。由于没有具体的博文内容,无法提供更详细的...
在`netty-4.1.0.CHM`这个文档中,你可以找到关于Netty 4.1.0版本的详细API说明,涵盖了所有核心组件、接口和类的使用方法,包括Channel、ByteBuf、EventLoopGroup、Pipeline、Handler等关键概念的解释,以及各种协议...
【Android开发问题集锦第一期】包含了多个关于Android开发中常见问题的解答,这些问题涵盖了图像处理、内存管理、Java特性的支持以及系统组件的使用等多个方面。以下是对这些问题的详细解释: 1. **Bitmap如何保存...
在博客“百度CSDN CRACENT”中,可能会有更深入的示例代码和详细的解释,帮助读者理解如何在实际项目中应用这些步骤。通过学习这个主题,开发者可以更好地处理低级别的数据操作,这对于处理特定格式的文件或者需要...
- 注意,为了提高效率和避免一次性加载大文件到内存,可以使用缓冲区(如ByteBuffer)分块传输。 5. **实验报告**: - 实验报告应包含实验目的、环境配置、步骤描述、问题分析和改进方案等部分。在描述实现过程时...
本帮助文档专注于在Android环境下使用JNI进行开发,提供了全面的API指南,全中文解释,便于国内开发者理解和应用。 1. JNI基础: - JNI头文件:开发JNI时,需要包含`<jni.h>`头文件,它定义了所有与JNI相关的类型...
以下是关于这个主题的详细解释。 首先,16进制是一种数字表示方式,每4个字符代表一个字节(8位)。浮点数在计算机内部通常是用二进制的格式存储的,具体分为两部分:符号位、指数部分和尾数部分。在Java中,浮点数...
5. 建立Block传输通道:客户端请求建立Block传输通道到DataNode,使用bytebuffer的形式请求建立通道。 6. 请求数据传输:客户端请求数据传输到DataNode,DataNode将数据写入磁盘。 7. 传输数据packet(chunk512+...
- 讲解了如何使用`java.nio`包中的类和方法,如`Selector`、`Channel`、`ByteBuffer`等,以及它们在实现高性能网络通信中的作用。 从以上提到的要点可以看出,Doug Lea在Java NIO方面的讲解非常全面,覆盖了从基础...
Android 开发问题集锦第一期涵盖了多个常见的Android开发难题,以下是对这些问题的详细解释: 问题一:Bitmap如何保存成为一个bmp文件 在Android中,Bitmap对象默认的压缩格式仅支持PNG和JPEG。要将Bitmap保存为BMP...