HeapByteBuffer 在jvm堆上面的一个buffer,底层的本质是一个数组  由于内容维护在jvm里,所以把内容写进buffer里速度会快些;并且,可以更容易回收
DirectByteBuffer 底层的数据其实是维护在操作系统的内存中,而不是jvm里,DirectByteBuffer里维护了一个引用address指向了数据,从而操作数据  跟外设(IO设备)打交道时会快很多,因为外设读取jvm堆里的数据时,不是直接读取的,而是把jvm里的数据读到一个内存块里,再在这个块里读取的,如果使用DirectByteBuffer,则可以省去这一步,实现zero copy
ByteBuffer的属性
byte[] buff  //buff即内部用于缓存的数组。
position //当前读取的位置。
mark //为某一读过的位置做标记,便于某些时候回退到该位置。
capacity //初始化时候的容量。是它所包含的元素的数量,缓冲区的容量不能为负并且不能更改
limit //当写数据到buffer中时,limit一般和capacity相等,当读数据时,limit代表buffer中有效数据的长度。

这些属性总是满足以下条件: 0 <= mark <= position <= limit <= capacity

ByteBuffer的常规方法
ByteBuffer allocate(int capacity) //创建一个指定capacity的ByteBuffer。
ByteBuffer allocateDirect(int capacity) //创建一个direct的ByteBuffer,这样的ByteBuffer在参与IO操作时性能会更好
ByteBuffer wrap(byte [] array)
ByteBuffer wrap(byte [] array, int offset, int length) //把一个byte数组或byte数组的一部分包装成ByteBuffer。
//get put方法不多说
byte get(int index)
ByteBuffer put(byte b)
int getInt()       //从ByteBuffer中读出一个int值。
ByteBuffer putInt(int value) // 写入一个int值到ByteBuffer中。
ByteBuffer的特殊方法
Buffer clear()    //把position设为0,把limit设为capacity,一般在把数据写入Buffer前调用。
Buffer flip()   //把limit设为当前position,把position设为0,一般在从Buffer读出数据前调用。
Buffer rewind() //把position设为0,limit不变,一般在把数据重写入Buffer前调用。和 clear() 类似,只是不改动限制
compact() //将 position 与 limit之间的数据复制到buffer的开始位置,复制后 position = limit -position,limit = capacity, 但如 果position 与limit 之间没有数据的话发,就不会进行复制。
mark() & reset() //通过调用Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用Buffer.reset()方法恢复到这个position。

put

写模式下,往buffer里写一个字节,并把postion移动一位。写模式下,一般limit与capacity相等。

flip

写完数据,需要开始读的时候,将postion复位到0,并将limit设为当前postion。

get

从buffer里读一个字节,并把postion移动一位。上限是limit,即写入数据的最后位置。

clear

将position置为0,并不清除buffer内容。

mark & reset

mark相关的方法主要是mark()(标记)和reset()(回到标记).

/**
* 1.txt => VipSoftAAA
*
* @throws Exception
*/
@Test
public void readFile() throws Exception {
FileChannel channel = FileChannel.open(Paths.get("D:\\temp\\1.txt"), StandardOpenOption.READ);
ByteBuffer buf = ByteBuffer.allocate(7);
while (channel.read(buf) != -1) {
buf.flip();
String ss = new String(buf.array());
System.out.println(ss); // 这种方式的读取,不会产生 position 的变化 int idx = 0;
while (buf.hasRemaining()) {
/**
* get() 后 position 会往后+1
* 如果执行完成后,没有 clear(),则新的文件内容不会被读出来。因为 position 已经到了 capacity 值了,没地方放新内容了
*/
System.out.print((char) buf.get());
if (idx == 2) {
/**
* 将 position 与 limit之间的数据复制到buffer的开始位置
* 复制后,position = (pos <= lim ? lim - pos : 0) 接着往后读
* 所以第二次取出AAA时,重置后,position =0 ,这时候会就把buf里面的数据重新再打印一遍变成 AAAAAAtoft
*/
buf.compact(); String compactStr = new String(buf.array());
System.out.println("\r\nCompact => " + compactStr); // compact后一次性读出来看变化,发现Soft被复制到了前面
}
idx++;
}
//第二次读出4个字节,但输出还是AAASoft,说明 clear 只是把 position 设为0, 并没有清除数据
buf.clear();
System.out.println();
}
channel.close();
System.out.println();
}
//输出结果:
//VipSoft //buf.array() 一次性打印全部,无偏移
//Vipoft //compact=7-3=4,所以跳过第三位的S,从第4位开始取值
//AAAtoft //一次性打印全部,因为 compact 将后position~limit的数据复制到了开始位置,所以AAA后面多了个 t
//AAAAAAtoft //第二次 pos>lim 所以 pos=0 把第一次的内容又打了一遍
拿第一个例子来分析,这三个属性的作用,capacity(容量)、limit(限制)和position(位置)

1.分配内存大小为10的缓存区。索引10的空间是我虚设出来,实际不存在,为了能明显表示capacity。IntBuffer的容量为10,所以capacity为10,在这里指向索引为10的空间。Buffer初始化的时候,limit和capacity指向同一索引。position指向0。

2.往Buffer里加一个数据。position位置移动,capacity不变,limit不变。

3.Buffer读完之后,往bufer里写了5个数据,position指向索引为5的第6个数据,capacity不变,limit不变。

4.执行flip()。这时候对照着,之前flip源码去看。把position的值赋给limit,所以limit=5,然后position=0。capacity不变。结果就是:

5.Buffer开始往外写数据。每写一个,position就下移一个位置,一直移到limit的位置,结束。

上图的顺序就是代码中的IntBuffer从初始化,到读数据,再写数据三个状态下,capacity,position,limit三个属性的变化和关系。

大家可以发现:
1. 0 <= position <= limit <= capacity
2. capacity始终不变

@Test
public void nioTest() {
// 分配内存大小为10的缓存区
IntBuffer buffer = IntBuffer.allocate(10);
System.out.println("capacity:" + buffer.capacity());
for (int i = 0; i < 5; ++i) {
System.out.println("put data position:" + buffer.position());
buffer.put(i+1);
}
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println(">>>>>>>> position:" + buffer.position());
System.out.println(">>>>>>>> limit:" + buffer.limit());
System.out.println(">>>>>>>> capacity:" + buffer.capacity());
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println(">>>>> flip() 使缓冲区为一系列新的通道写入或相对获取 操作做好准备<<<<<");
buffer.flip();
System.out.println("after flip limit:" + buffer.limit());
System.out.println("enter while loop");
while (buffer.hasRemaining()) {
System.out.println(">>>>>>>> position:" + buffer.position());
System.out.println(">>>>>>>> limit:" + buffer.limit());
System.out.println(">>>>>>>> capacity:" + buffer.capacity());
System.out.println(">>>>>>>> 元素:" + buffer.get());
}
System.out.println(">>>>> rewind() 将位置 position = 0 也就是相当于选取当前缓冲区总的全部有效数据 和clear()类似,只是不改动限制 <<<<<");
buffer.rewind();
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println(">>>>>>>> position:" + buffer.position());
System.out.println(">>>>>>>> limit:" + buffer.limit());
System.out.println(">>>>>>>> capacity:" + buffer.capacity());
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println(">>>>> clear() 用来初始化缓存空间,例如读取文件时将文件内容置入缓存时要先执行此方法 <<<<<");
buffer.clear();
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println(">>>>>>>> position:" + buffer.position());
System.out.println(">>>>>>>> limit:" + buffer.limit());
System.out.println(">>>>>>>> capacity:" + buffer.capacity());
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
}

ByteBuffer 字节缓冲区的更多相关文章

  1. Java基础知识强化之IO流笔记28:BufferedOutputStream / BufferedInputStream(字节缓冲区流) 之BufferedOutputStream写出数据

    1. BufferedOutputStream / BufferedInputStream(字节缓冲区流)的概述 通过定义数组的方式确实比以前一次读取一个字节的方式快很多,所以,看来有一个缓冲区还是非 ...

  2. 【转】Socket接收字节缓冲区

    原创本拉灯 2014年04月16日 10:06:55 标签: socket / 数据包 4448 我们接收Socket字节流数据一般都会定义一个数据包协议( 协议号,长度,内容),由于Socket接收 ...

  3. Java中的字节流,字符流,字节缓冲区,字符缓冲区复制文件

     一:创建方式 1.建立输入(读)对象,并绑定数据源 2.建立输出(写)对象,并绑定目的地 3.将读到的内容遍历出来,然后在通过字符或者字节写入 4.资源访问过后关闭,先创建的后关闭,后创建的先关闭 ...

  4. Java基础-虚拟内存之映射字节缓冲区(MappedByteBuffer)

    Java基础-虚拟内存之映射字节缓冲区(MappedByteBuffer) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.映射字节缓冲区 1>.什么是虚拟内存 答:虚拟内 ...

  5. Java SocketChannel 读取ByteBuffer字节的处理模型

    在JAVA中的流分为字节流或字符流,一般来说采用字符流处理起来更加方便.字节流处理起来相对麻烦,SocketChannel中将数据读取到ByteBuffer中,如何取出完整的一行数据(使用CRLF分隔 ...

  6. 牛客网Java刷题知识点之字节缓冲区练习之从A处复制文本文件到B处(BufferedReader、BufferedWriter)、复制文本文件的原理图解

    不多说,直接上干货! CopyTextByBufTest.java package zhouls.bigdata.DataFeatureSelection.test; import java.io.B ...

  7. NIO之缓冲区

    NIO引入了三个概念: Buffer 缓冲区 Channel 通道 selector 选择器 1.java.io优化建议 操作系统与Java基于流的I/O模型有些不匹配.操作系统要移动的是大块数据(缓 ...

  8. NIO基础学习——缓冲区

    NIO是对I/O处理的进一步抽象,包含了I/O的基础概念.我是基于网上博友的博客和Ron Hitchens写的<JAVA NIO>来学习的. NIO的三大核心内容:缓冲区,通道,选择器. ...

  9. Java NIO之套接字通道

    1.简介 前面一篇文章讲了文件通道,本文继续来说说另一种类型的通道 -- 套接字通道.在展开说明之前,咱们先来聊聊套接字的由来.套接字即 socket,最早由伯克利大学的研究人员开发,所以经常被称为B ...

  10. java网络编程学习之NIO模型

    网上对NIO的解释有很多,但自己一直没有理解,根据自己的理解画出下面这个图,有什么不对的地方,欢迎留言指出. 理解是,客户端先与通过通道Channel与连接(注册到服务器端),然后再传送数据,服务器端 ...

随机推荐

  1. Go 方法集合与选择receiver类型

    Go 方法集合与选择receiver类型 目录 Go 方法集合与选择receiver类型 一.receiver 参数类型对 Go 方法的影响 二.选择 receiver 参数类型原则 2.1 选择 r ...

  2. c#中责任链模式详解

    基本介绍:   "责任链"顾名思义,是指一个需要负责处理请求的链条.   每个链条节点都是一个单独的责任者,由责任者自己决定是否处理请求或交给下一个节点.   在设计模式中的解释则 ...

  3. 平台工程时代的 Kubernetes 揭秘:2023年生产状况报告深度剖析

    Kubernetes 在生产环境中的复杂性已经成为常态,在2023年这个平台工程盛行的时代,容器管理的最大亮点可能在于其灵活性,然而在运维政策和治理等方面仍然存在诸多挑战.八年过去了,在生产环境中使用 ...

  4. C#中的virtual和override关键字

    公众号「DotNet学习交流」,分享学习DotNet的点滴. 使用基类中的引用 代码如下: class MyBaseClass //基类   {        public void Print() ...

  5. jmeter-逻辑处理器while

    测试工具:jmeter 业务逻辑:A接口上传文件,B接口查询文件上传状态,如果状态不为4,需要再次查询(上传文件后,需要有短暂时间的识别,压测时并发大导致识别时间不可控)当为4时,跳出循环, 思路:增 ...

  6. CICD实践1:环境安装篇

    一.CICD技术选型 配置管理工具 工具 需求管理工具 使用禅道 代码管理工具 使用Gitlab 编译构建工具 搭建Jenkins,使用Jenkinsfile 制品库工具 nexus 文档管理工具 C ...

  7. Tensorflow2.0实现VGG13

    导入必要的库: import os import tensorflow as tf from tensorflow import keras from tensorflow.keras import ...

  8. 华企盾DSC可能造成系统蓝屏奔溃常见处理方法

    1.蓝屏先卸载我们DSC客户端检测是否是我们影响的 2.如果是我们影响的查到版本说明是否有处理过 3.是否有一些不常用的杀毒软件卸载试试 4.如果使用一些USB驱动类的先把USB的注册表改一下试试 5 ...

  9. 华企盾DSC导致导出文件报错常见处理方法

    1.导出文件的进程和打开该文件的进程启用OLE控制是否都是未勾选,以及启用虚拟重定向是否设置一致(要么都勾选要么都不勾) 2.用procmon监控个人模式下导出非加密的文件,搜索writefile的进 ...

  10. MinIO客户端之license

    MinIO提供了一个命令行程序mc用于协助用户完成日常的维护.管理类工作. 官方资料 mc license mc license info mc license register mc license ...