定义:

ByteBuffer是Buffer的实现类之一,是一个通用的缓冲区,功能要比其他缓冲区子类多。支持直接内存。是一个抽象类。子类实现是HeapByteBuffer(非直接缓冲区子类),DirectByteBuffer(直接缓冲区子类)。

看此文前建议看看:
关于Buffer可以查看 Java NIO学习篇之缓冲区Buffer详解

直接缓冲区:


以上是书《深入理解Java虚拟机》对直接内存的描述。简单来说直接内存不是JVM内存,而是计算机真正的物理内存。

我们IO中有个步骤是:
读:把内核缓冲区的数据复制到用户缓冲区。
写:把用户缓冲区的数据复制到内核缓冲区。

而使用直接缓冲区可以使得内核缓冲区和用户缓冲区映射到同一块物理内存地址上,使得可以省略复制步骤,实现零拷贝,提高效率。

这里它不是侧重点,简单了解下就好。

常用API详解(是对应子类HeapByteBuffer的效果):

获取ByteBuffer对象的API

//获取ByteBuffer对象的方法//1. 获取非直接缓冲区的ByteBuffer,capacity参数指定缓冲区容量。
public static ByteBuffer allocate(int capacity);//2. 通过传入一个字节数组来获取ByteBuffer对象。相当于把传进来的字节数组封装成一个ByteBuffer对象。
//如果传进来的数组有数据的话,可以直接进行读,此时ByteBuffer会处于读模式。创建的初始ByteBuffer的
//limit=该数组的长度length,position=0,所以读取的话会完全读取该数组的。
public static ByteBuffer wrap(byte[] array);//3.  通过传入一个字节数组来获取ByteBuffer对象。相当于把传进来的字节数组封装成一个ByteBuffer对象。并且可以指定position(用参数offset指定),limit(用length+offset指定)。
public static ByteBuffer wrap(byte[] array,int offset, int length)///以上三种方法获取的都是非直接缓冲区///4.获取直接缓冲区,并用capacity指定缓冲区的大小。
public static ByteBuffer allocateDirect(int capacity)
public class ByteBufferDemo {public static void main(String[] args) {ByteBuffer byteBuffer = ByteBuffer.allocate(1024);System.out.println("============>>>allocate(int)<<<<==================");System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byte[] b1 = new byte[1024];ByteBuffer byteBuffer1 = ByteBuffer.wrap(b1);System.out.println("============>>>wrap(byte[])<<<<==================");System.out.println("position = " + byteBuffer1.position());System.out.println("limit = " + byteBuffer1.limit());System.out.println("capacity = " + byteBuffer1.capacity());byte[] b2 = new byte[1024];ByteBuffer byteBuffer2 = ByteBuffer.wrap(b1,10,500);System.out.println("============>>>wrap(byte[],int,int)<<<<==================");System.out.println("position = " + byteBuffer2.position());System.out.println("limit = " + byteBuffer2.limit());System.out.println("capacity = " + byteBuffer2.capacity());System.out.println("============>>>allocateDirect(int)<<<<==================");ByteBuffer byteBuffer3 = ByteBuffer.allocateDirect(1024);System.out.println("position = " + byteBuffer3.position());System.out.println("limit = " + byteBuffer3.limit());System.out.println("capacity = " + byteBuffer3.capacity());}
}

执行结果:

对缓冲区写数据的API

//往缓冲区中写入一个字节的数据,游标右移一位。返回缓冲区自身,可进行链式写入。
public abstract ByteBuffer put(byte b);//往缓冲区数组的某个位置写入一个字节数据,返回缓冲区自身,可进行链式写入。此操作不会使游标移动。
public abstract ByteBuffer put(int index, byte b);//往缓冲区中添加另一个缓冲区的数据,会读取参数src的position到limit-1下标的数据。
//如果该src的可读数据长度比调用该方法的可写缓冲区的数据长度长的话,就会报错。
public ByteBuffer put(ByteBuffer src);//往缓冲区里面添加一个字节数组,并可以指定src数组的偏移量和长度。
//添加之后缓冲区的position=oldPsition+length
public ByteBuffer put(byte[] src, int offset, int length);//往缓冲区里面添加一个字节数组,添加完后position=oldPsition+lengthpublic final ByteBuffer put(byte[] src)

demo:

 public static void  testPut(){ByteBuffer byteBuffer = ByteBuffer.allocate(10);System.out.println("==================>>>初始<<<=====================");System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.put((byte) 5);System.out.println("==================>>>ByteBuffer put(byte b)<<<=====================");System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.clear();byteBuffer.put(2,(byte) 5);System.out.println("==================>>>put(int index, byte b)<<<=====================");System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.clear();//源缓冲区ByteBuffer src = ByteBuffer.allocate(5);src.put("hh".getBytes());src.flip();byteBuffer.put(src);System.out.println("==================>>>put(ByteBuffer src)<<<=====================");System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.clear();byte[] bytes = new byte[5];byteBuffer.put(bytes,1,3);System.out.println("==================>>>put(byte[] src, int offset, int length)<<<=====================");System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.clear();byteBuffer.put(bytes);System.out.println("==================>>>put(byte[] src)<<<=====================");System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.clear();}

结果:

获取缓冲区数据的API


//读取缓冲区的下一字节数据,position右移一位。
public abstract byte get();//读取缓冲区的指定下标字节数据,position不移动。
public abstract byte get(int index);//读取缓冲区的数据到dst数组,可以指定读到dst的偏移量和读取数据的长度。
//position右移length。
//返回自身,可链式调用
public ByteBuffer get(byte[] dst, int offset, int length);//读取缓冲区的数据到dst数组。
//position右移dst.length()。
//返回自身,可链式调用
public ByteBuffer get(byte[] dst);

demo:

public static void testGet(){ByteBuffer byteBuffer = ByteBuffer.allocate(10);byteBuffer.put("helloworld".getBytes());byteBuffer.flip();System.out.println("==================>>>初始<<<=====================");System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byte b = byteBuffer.get();System.out.println("==================>>>get()<<<=====================");System.out.println(new String(new byte[]{b}));System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.clear();byteBuffer.put("helloworld".getBytes());byteBuffer.flip();byte b1 = byteBuffer.get(2);System.out.println("==================>>>get(int index)<<<=====================");System.out.println(new String(new byte[]{b1}));System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.clear();byteBuffer.put("helloworld".getBytes());byteBuffer.flip();byte[] bytes = new byte[byteBuffer.remaining()];byteBuffer.get(bytes);System.out.println("==================>>>get(byte[] dst, int offset, int length)<<<=====================");System.out.println(new String(bytes));System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.clear();byteBuffer.put("helloworld".getBytes());byteBuffer.flip();byte[] bytes1 = new byte[byteBuffer.remaining()];byteBuffer.get(bytes1,5,5);System.out.println("==================>>>get(byte[] dst)<<<=====================");System.out.println(new String(bytes1,5,5));System.out.println("position = " + byteBuffer.position());System.out.println("limit = " + byteBuffer.limit());System.out.println("capacity = " + byteBuffer.capacity());byteBuffer.clear();}

结果:

其他API:

//返回一个只读缓冲区,返回的缓冲区与原本的缓冲区不是同一个缓冲区,是不同的对象。
//与原本缓冲区的数据和元数据都一样,只是他是只读的。
public ByteBuffer asReadOnlyBuffer();//返回一个int缓冲区。其他类型的也差不多。
public IntBuffer asIntBuffer();//将字节缓冲区的当前position加后面3位byte数据(共四位)转换成一个int类型返回。
//游标position右移4
public abstract int getInt();//将字节缓冲区的i下标加后面3位byte数据(共四位)转换成一个int类型返回。
//游标不移动
public int getInt(int i) //将value值存进缓冲区当前position+后3位,存进去。
//游标position右移4
putInt(int value);//将value值存进缓冲区index+后3位,存进去。
//游标不移动
putInt(int index, int value)//上面的操作其他类型的相关操作类似,只是转成的byte数组长度不一样,例如int会转成4,long转成8.////返回一个当前ByteBuffer 的副本。是一个新对象。
public ByteBuffer duplicate();

其他六种基本类型的缓冲区API与ByteBuffer的子集类似,有些只是多了解码编码,所以,只要学会ByteBuffer的API差不多等于学会了其他六种基本类型的API。

Java NIO学习篇之缓冲区ByteBuffer详解相关推荐

  1. Java NIO学习篇之缓冲区CharSet详解

    定义: CharSet是对java nio编码解码的解决方案,专门负责字符的编码和解码. 编码:字符数组.字符串 ===> 字节数组. 解码:字节数组 ==> 字符数组.字符串 API详解 ...

  2. Java NIO学习篇之缓冲区Buffer详解

    定义 缓冲区Buffer在java nio中负责数据的存储,缓冲区就是数组,用于存储不同类型数据的数组. jdk为java七大基本类型数据都准备了响应的缓冲区(boolean值除外): ByteBuf ...

  3. Java NIO学习篇之通道FileChannel详解

    定义: FileChannel是Java NIO对应于磁盘等存储设备文件操作的通道. 常用API详解: 获取FileChannel的API /** * 打开一个与文件的连接通道,用于进行文件操作. * ...

  4. Java NIO学习篇之通道Channel详解

    定义: Channel:通道,运输的介质,可以大致比喻成铁路的铁轨,连接着两个车站,而channel用于打开与IO设备的连接,比如磁盘,套接字等. 通道使用完需要关闭. 与传统IO的Stream比较: ...

  5. Java NIO学习篇之直接缓冲区和非直接缓冲区

    定义 以上是书深入理解java虚拟机对直接内存的描述.直接缓冲区用的就是直接内存. java nio字节缓冲区要么是直接的,要么是非直接的.如果为直接字节缓冲区,则java虚拟机会尽最大努力直接在此缓 ...

  6. java 检查bytebuf长度_Java学习笔记16-Netty缓冲区ByteBuf详解

    Java学习笔记16-Netty缓冲区ByteBuf详解 Netty自己的ByteBuf ByteBuf是为解决ByteBuffer的问题和满足网络应用程序开发人员的日常需求而设计的. JDK Byt ...

  7. Java NIO学习笔记之图解ByteBuffer

    转载自 Java NIO学习笔记之图解ByteBuffer ByteBuffer前前后后看过好几次了,实际使用也用了一些,总觉得条理不够清晰. <程序员的思维修炼>一本书讲过,主动学习,要 ...

  8. [网络安全学习篇2]:IP详解及简单的DOS命令(千峰网络安全视频笔记 2 day)

    引言:我的系列博客[网络安全学习篇]上线了,小编也是初次创作博客,经验不足:对千峰网络信息安全开源的视频公开课程的学习整理的笔记整理的也比较粗糙,其实看到目录有300多集的时候,讲道理,有点怂了,所以 ...

  9. Java NIO学习篇之NIO的基本认识

    定义: NIO:是从jdk1.4提出的,本意是New IO(相对于传统的IO),也叫 No Blocked IO(只相对于网络IO),它的出现弥补传统IO的不足,提出了更加高效的方式. NIO对于网络 ...

最新文章

  1. 学懂分析,玩转大数据
  2. SAP WM 如何理解使用LT0G撤销TO时系统出现的锁的标志
  3. 【追寻javascript高手之路04】理解prototype
  4. diamond源码阅读-diamond-client
  5. c 语言 文本处理范例
  6. 牛客题霸 NC8 二叉树根节点到叶子节点和为指定值的路径
  7. IIS添加直接下载的文件类型
  8. oracle按位或运算符怎么用,Oracle按位运算符
  9. java输入一个矩阵顺时针打印_剑指Offer(Java版):顺时针打印矩阵
  10. 谁先看到苏神咬人? 世界杯直播背后的云
  11. 解析Web应用服务四大弱点
  12. QCC305x系列开发教程(入门篇)之1.3-烧录方式使用USB时的驱动安装及其出现“未知设备”的解决方法
  13. 编写PC操作系统的参考资料(不断更新)
  14. #编写一个函数,实现接受一个字符串,分别统计大写字母、小写字母、数字、其他字符的个数,并且返回结果
  15. 《神奇的数学》读后感_《走进奇妙的数学世界》读后感
  16. 作为一名架构师,懂点硬件知识不过分吧?
  17. css清除浮动的方法及原因
  18. spring 事务中先删除再插入后唯一键冲突 delete then insert duplicate key
  19. 日本python教程视频_清华学姐推荐的python视频400集,拿走不谢
  20. 一个诗人的一生——诗人小G的人生

热门文章

  1. 大数据学习笔记56:HBase Shell操作
  2. Python编程基础08:循环结构
  3. 【BZOJ1815BZOJ1488】有色图图的同构,Polya计数+暴力
  4. Intel 64/x86_64/IA-32/x86处理器 - 通用指令(5) - 控制转移指令
  5. php 缩略图不失真,c#生成缩略图不失真的方法实例分享
  6. java键盘输入到文件中_在Linux中使用java和javac命令编译运行java文件
  7. 音频特效:Delay 和 Vibrato
  8. devops之路rancher安装
  9. 在SOUI中使用线性布局
  10. Hadoop集群部署权限总结