Java NIO下ByteBuffer的常用方法学习|全球热闻
2023-05-17 11:57:24 来源:脚本之家
目录
前言文件读取案例代码展示打印结果BufferByteBuffer常用方法工具方法 selectAll()初始化buffer.put()buffer.get()buffer.flip()buffer.rewind()buffer.mark() & buffer.reset()buffer.clear() & buffer.compact()全部代码前言
咱就说,基础不牢地动山摇,以前欠下的债迟早都要补回来,开始安排 Netty, 从 NIO 开始学起, 学习嘛, 肯定是先从案例开始学起
今日任务:
(资料图片仅供参考)
初步学习 NIO 中的 ByteBuffer
文件读取案例
一个小小的案例, 读取 test.txt 文件的内容, 四步走:
获取文件流准备缓冲区写入缓冲区遍历读取代码展示
private static void getFileContent(){ // 输入输出流 try(FileChannel channel = new FileInputStream("C:\Users\My\Desktop\learn\demo\demo\test.txt").getChannel()){ // 准备缓冲区 ByteBuffer buffer = ByteBuffer.allocate(10); // 循环遍历 while(true){ // 从 channel 读取数据, 向 buffer 写入 int len = channel.read(buffer); if (len == -1){ System.out.println("没有内容了"); break; } // 打印 buffer 内容 // 切换至 读模式 buffer.flip(); // 遍历查看是否还有剩余未读数据 while(buffer.hasRemaining()){ byte b = buffer.get(); System.out.println(b); } // 切换为写模式 buffer.clear(); } }catch (Exception e){ System.out.println("文件未找到"); } }
打印结果
test.txt文件内容如下所示
接下来执行上述代码, 结果如下
可以看到打印出来的结果是 ASCII 编码表的值,所以我们把输出转为 char 类型, 结果如下
Buffer
Buffer继承自Object类,是基本类型元素的线性有限序列(容器)。除内容外,Buffer的基本属性有:Limit—限制,Capacity—容量,Position—位置。对着三个变量操作,可以完成几乎所有对Buffer的代码操作。
今天开始学习 Netty ,那就绕不过 NIO, 在 NIO 包下的 Buffer 有以下七种实现:
ByteBufferShortBufferFloatBufferCharBufferDoubleBufferIntBufferLongBuffer实际上就是八种数据类型的相关 Buffer, 但是我只听说过 ByteBuffer, 也是使用最广泛的, 至于为什么我也不知道, 希望以后有机会能过来填坑, 有大佬知道的话也可以评论区说一下
ByteBuffer常用方法
在 java 中 ByteBuffer 的常用方法有以下七种:
put: 写入get: 读数据flip: 切换读模式rewind: 重新重头开始读mark: 记录当前下标reset: 回到 mark 位置clear: 切换写模式compact: 切换写模式, 同时将未读数据移动到首部工具方法 selectAll()
为了方便观察当前 ByteBuffer 所处的位置, 容量等信息, 写了下面这个方法
private static void selectAll(ByteBuffer buffer){ System.out.println(); int limit = buffer.limit(); System.out.print("pos = " + buffer.position() + " " + "lim = " + buffer.limit() + " " + "cap = " + buffer.capacity()); System.out.println(); for (int i = 0; i < limit; i++) { if (i < 10){ System.out.print(" | "); }else{ System.out.print(" | "); } System.out.print(i); } System.out.println(); System.out.println("--------------------------------------------------------------------------"); for (int i = 0; i < limit; i++) { byte b = buffer.get(i); System.out.print(" | "); System.out.print((char) b); if (b == 0){ System.out.print(0); } } System.out.println(); }
打印结果如下:
根据打印结果我们可以很直观的看到当前 ByteBuffer 每个下标上的元素是什么, 同时也能看到当前指针所处的位置(Position)
初始化
以下测试用例的 ByteBuffer 采用同一个 ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.put()
put方法就是往 ByteBuffer 中写入数据, 具体操作如下述代码所示
private static void bufferPut(ByteBuffer buffer){ buffer.put(new byte[]{"a", "b", "c", "d"}); selectAll(buffer); buffer.put(new byte[]{"1"}); selectAll(buffer); }
执行结果如下:
图中和代码一样, 是分两次打印当前 ByteBuffer 的内容, pos 就是下一次写入的下标
buffer.get()
get方法是获取元素的, 但是我们如果在刚写入之后就去读取的话, 是什么都读取不到的, 具体如下所示
可以看到, 我们读取出来当前的元素为 0, 我们进入源码看一下 get 方法
如图所示, 我们通过 get 方法获取到的元素都是当前 pos 的下一个坐标元素, 在之前的 put 方法中, 我们看到最后 pos 是指向了 5 是下一个 写入下标
我们有两种方法可以获取到元素:
通过下标获取将写入模式更改为读模式通过下标获取: 直接输入下标就可以获取到了
buffer.flip()
flip方法: 将读模式转换为写模式
还是刚才的例子, 使用方法 buffer.flip() 之后, 可以看到 pos变成了 1, lim变成了 5 , cap不变
这里 pos代表的是下一个 get的下标, lim代表的是当前的长度
注意: 在调用 flip 进入读模式之后,后续如果调用get()
导致position
大于等于了limit
的值,程序会抛出BufferUnderflowException
异常。这点从之前get
的源码也可以看出来。
buffer.rewind()
rewind方法可以理解为下标归零, 也可以理解为重新开始, 重头开始. 代码展示如下所示
我们点进源代码也可以看到, 它实际上就是将 pos 赋值了 0, 将 mark 赋值为 -1
buffer.mark() & buffer.reset()
这里将 mark方法和 reset方法一起讲, 他俩是相辅相成的一个关系, 二者缺一不可
mark方法标记当前下标, reset回到 mark 标记的下标
可以看到, 当我们执行 mark方法的时候记录了当前的下标, 执行 reset方法的时候 pos 又更改为了 1
buffer.clear() & buffer.compact()
clear方法和 compact方法都是对当前 ByteBuffer 写入 , clear方法是从头开始写入, compact方法是将未读内容移至头部然后再写入
可以看到, 在执行完 clear方法之后, 新增的元素是从下标 0 开始写入的
可以看到, 在执行完 compact方法之后, 它先是将没有读取到的数据放置头部, 在接下来 put的时候对后面的内容进行了一个覆盖
全部代码
import java.io.FileInputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; /** * @Author ningxuan * @Date 2022/10/31 21:28 */ public class ByteBufferTest { public static void main(String[] args) { // 读文件案例 // getFileContent(); // 初始化 ByteBuffer ByteBuffer buffer = ByteBuffer.allocate(16); // 写测试 bufferPut(buffer); // a , b , c , d, 1 bufferGet(buffer); buffer.flip(); // System.out.println((char) buffer.get()); // a pos == 0 // System.out.println((char)buffer.get()); // b pos == 1 // buffer.rewind(); // System.out.println((char)buffer.get()); // c pos == 0 // System.out.println((char)buffer.get()); // d pos == 1 // bufferMarkTest(buffer); bufferCompact(buffer); } private static void bufferCompact(ByteBuffer buffer){ selectAll(buffer); buffer.get(); buffer.get(); selectAll(buffer); buffer.compact(); selectAll(buffer); buffer.put(new byte[]{"e", "h"}); selectAll(buffer); } private static void bufferClear(ByteBuffer buffer){ selectAll(buffer); System.out.println(); buffer.clear(); buffer.put(new byte[]{"e", "h"}); selectAll(buffer); } private static void bufferMarkTest(ByteBuffer buffer){ byte b; b = buffer.get(); // a System.out.println((char) b); buffer.mark(); System.out.println("position = " + buffer.position()); b = buffer.get(); // b System.out.println((char) b); b = buffer.get(); // c System.out.println((char) b); buffer.reset(); System.out.println("position = " + buffer.position()); b = buffer.get(); // b System.out.println((char) b); b = buffer.get(); // c System.out.println((char) b); } private static void bufferGet(ByteBuffer buffer){ byte b = buffer.get(0); // System.out.println((char)b); b = buffer.get(1); // System.out.println((char)b); } private static void bufferPut(ByteBuffer buffer){ buffer.put(new byte[]{"a", "b", "c", "d"}); // selectAll(buffer); buffer.put(new byte[]{"1"}); // selectAll(buffer); } private static void selectAll(ByteBuffer buffer){ System.out.println(); int limit = buffer.limit(); System.out.print("pos = " + buffer.position() + " " + "lim = " + buffer.limit() + " " + "cap = " + buffer.capacity()); System.out.println(); for (int i = 0; i < limit; i++) { if (i < 10){ System.out.print(" | "); }else{ System.out.print(" | "); } System.out.print(i); } System.out.println(); System.out.println("--------------------------------------------------------------------------"); for (int i = 0; i < limit; i++) { byte b = buffer.get(i); System.out.print(" | "); System.out.print((char) b); if (b == 0){ System.out.print(0); } } System.out.println(); } private static void getFileContent(){ // 输入输出流 try(FileChannel channel = new FileInputStream("C:\Users\My\Desktop\learn\demo\demo\test.txt").getChannel()){ // 准备缓冲区 ByteBuffer buffer = ByteBuffer.allocate(10); // 循环遍历 while(true){ // 从 channel 读取数据, 向 buffer 写入 int len = channel.read(buffer); if (len == -1){ System.out.println("没有内容了"); break; } // 打印 buffer 内容 // 切换至 读模式 buffer.flip(); // 遍历查看是否还有剩余未读数据 while(buffer.hasRemaining()){ byte b = buffer.get(); System.out.println((char) b); } // 切换为写模式 buffer.clear(); } }catch (Exception e){ System.out.println("文件未找到"); } } }
以上就是Java NIO下ByteBuffer的常用方法学习的详细内容,更多关于Java ByteBuffer的资料请关注脚本之家其它相关文章!
关键词:
为你推荐
陕西两万五千吨市政桥梁完成“转身”
兰州40家A级旅游景区暂时关闭 开放时间暂定
北京丰台初步排查确诊病例密接、次密接258人 组织3万余
四川95岁战斗英雄何开仲有个心愿:想见见山东老战友
增产快!电力生产加速 能源供应偏紧将得到缓解
夏粮和早稻实现双增产 前三季度农林牧渔业增加值同比增
云南瑞丽江桥“守门员”:疫情防控不漏一人
“久病床前真孝子” 浙江男子照顾瘫痪母亲十载
黑龙江:儿童福利机构养育儿童保障标准提至1750元
山西新绛南关村民:因洪水离开家的日子
“十年磨一剑” 黑色矸石山终闻花果香
国家一级保护动物猎隼受伤 内蒙古警方送医救治
一罪犯强行脱逃下落不明 吉林省吉林监狱发布悬赏通告
涉案金额逾3000万 广西一“洗钱”团伙受审
青藏高原有雨雪天气 西南地区江南华南等地有明显降雨
湖南长沙县发现1例外省输入新冠肺炎确诊病例
青海互助:打造全国最大高原草莓种苗繁育中心
照片修复师:每修复一张照片越珍惜与亲人相处的时光
贵州率先在中国实现地质矿产勘查全过程数字化
浙江岱山通报一船沉没 2人获救11人失联
推荐内容
- 陕西两万五千吨市政桥梁完成“转身”
- 河北邯郸发生天然气泄漏事故致3人死亡
- 兰州40家A级旅游景区暂时关闭 开放时间暂定
- 湖北警方打掉两跨省“跑分”洗钱犯罪团伙
- 新冠肺炎疫情下如何保护孩子?张文宏建议设儿童专
- 海南儋州出现1例治愈后的境外输入病例复阳人员
- 男童脊柱侧弯压迫心肺 医生耗时7小时矫正
- 宁夏将开展18岁以上重点人群加强免疫接种工作
- 北京新增1例京外关联本地确诊病例 病例所在街道
- 北京丰台初步排查确诊病例密接、次密接258人 组
- 四川95岁战斗英雄何开仲有个心愿:想见见山东老战
- 增产快!电力生产加速 能源供应偏紧将得到缓解
- 夏粮和早稻实现双增产 前三季度农林牧渔业增加值
- 云南瑞丽江桥“守门员”:疫情防控不漏一人
- 宁夏吴忠核酸阳性者已确诊
- 宁夏吴忠市发现一例外省来吴核酸检测阳性人员
- “久病床前真孝子” 浙江男子照顾瘫痪母亲十载
- 内蒙古额济纳旗5名确诊病例行动轨迹:在同一饭店
- 北京疾控:近期去过这些地方的相关人员请主动报备
- 北京新增1例京外关联输入本地确诊病例
- 增强为民服务能力——做群众最盼事 解群众最难题
- 魏复盛:干一些平凡的实事
- 中缅边境畹町海关查获涉嫌走私海马干4381尾
- 黑龙江:儿童福利机构养育儿童保障标准提至1750元
- 山西新绛南关村民:因洪水离开家的日子
- “十年磨一剑” 黑色矸石山终闻花果香
- 适老化的游戏准备好了吗?电子游戏别忽视老年人
- 国家一级保护动物猎隼受伤 内蒙古警方送医救治
- 西安鄠邑发布2名密接者活动轨迹
- 宁夏吴忠发现一例外省来吴核酸检测阳性人员
- 上海籍阳性夫妻内蒙古行程涉及3个景区、1个民宿、
- 内蒙古额济纳旗启动IV级应急响应 排查出密接者197人
- 内蒙古二连浩特市两地调整为中风险地区
- 泥若二审宣判来了 知名游戏主播山泥若被判刑3年
- 河北邯郸发生天然气泄漏 3人窒息死亡
- 北京丰台报告1例甘肃来京人员新冠病毒核酸检测阳性
- 内蒙古二连浩特两个社区调整为中风险地区
- 一罪犯强行脱逃下落不明 吉林省吉林监狱发布悬赏
- 兰州6人核酸检测呈阳性 主城区局地调整为中风险区
- 涉案金额逾3000万 广西一“洗钱”团伙受审
油气
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10