Java NIO下ByteBuffer的常用方法学习
脚本之家 2023-05-17 12:07:45
目录
前言文件读取案例代码展示打印结果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的资料请关注脚本之家其它相关文章!

Java NIO下ByteBuffer的常用方法学习

2023-05-17 12:07:45

忍无可忍行拘5天!男子不戴头盔骑车逆行还辱骂交警

2023-05-17 11:44:34

增设既有住宅电梯40部 雁江全力推进既有住宅加装电梯工作

2023-05-17 11:15:29

与“沪宁杭”竞速,苏州如何突围?

2023-05-17 10:54:56

字体大小设置为23磅 字体大小设置

2023-05-17 10:04:34

2023年英文感谢信(汇总4篇)

2023-05-17 10:03:25

今日热讯:深夜22点,周琦宣布生涯意外决定,辽篮惊喜,赵继伟摊牌了

2023-05-17 09:17:11

今头条!“摧毁爱国者!”

2023-05-17 07:49:11

多家上市公司称二季度订单呈增长趋势 结构性复苏或促业绩增长

2023-05-17 06:49:19

环球快播:平潭一沙地囤放大量猪粪尿!村民:臭味弥漫,饱受其苦

2023-05-17 06:00:41

国羽苏杯2连胜提前出线,石宇奇何冰娇建功,男双组合丢掉一局 焦点快报

2023-05-17 04:42:37

胎动什么时候开始_胎动时间

2023-05-17 01:45:10

世界最资讯丨当日快讯:翰博高新收年报问询函:要求公司分析2022年年 2023年一季度收入及净利润下滑的原因

2023-05-16 22:48:30

宁夏筑铭广告装饰有限公司-今日播报

2023-05-16 21:52:41

【全球热闻】《漫长的季节》如此成功,伊能静怎能不“夫贵妻荣”?

2023-05-16 21:11:03

天天资讯:辽阳市气象局发布大风蓝色预警【Ⅳ级/一般】【2023-05-16】

2023-05-16 20:29:39

青岛双星: 关于部分限制性股票回购注销完成的公告

2023-05-16 19:31:24

合计24.9GW!内蒙古、甘肃第三批风光大基地清单出炉 天天热门

2023-05-16 18:49:13

【全球速看料】常熟纺机:以专精特新贡献“长方力量”

2023-05-16 18:05:04

全球观天下!一场声音沉浸之旅!Baseus倍思音频品鉴会正式召开

2023-05-16 17:48:36

看热讯:ST信通: 公司主营业务正常,ST并不影响公司正常的生产经营及产品研发

2023-05-16 17:16:02

【新要闻】女厨挑战100小时不间断做饭,4天没睡眼神呆滞,打破世界最长烹饪时间纪录

2023-05-16 16:45:31

天天新动态:《无畏契约》国服内测定档6月8日 规模更大内容更多

2023-05-16 16:21:47

巨一科技(688162)5月16日主力资金净买入90.60万元

2023-05-16 15:49:56

环球观察:银行降息潮来袭,智能存款停售,商业银行们大动作不断想干啥?

2023-05-16 15:24:15

安徽母女三人溺亡因婆家重男轻女?官方:暂无证据,三年前已离婚

2023-05-16 14:58:42

关于大自然手抄报版面设计图大全_关于大自然的手抄报资料_全球观天下

2023-05-16 13:55:06

戴维斯季后赛场均超20分12板3帽,NBA历史第五人 天天微速讯

2023-05-16 13:24:35

观察:出入境政策再优化 全国各口岸全面恢复快捷通关

2023-05-16 12:21:53

今日播报!广西河池教育局:2023广西河池中考成绩查询入口、查分网站

2023-05-16 11:23:56

恒瑞医药:回购周期预计一年左右,完成后再考虑具体分配方案

2023-05-16 10:58:41

洁神饭庄(洁神)

2023-05-16 10:25:05

环球速递!瑞星安全助手_关于瑞星安全助手介绍

2023-05-16 10:21:52

未成年人偷玩游戏 专家建议进网游时强化人脸识别

2023-05-16 09:50:24

我的久保田割草机过热

2023-05-16 09:20:45

当前关注:520婚姻登记火热,多地宣布为“爱”加班

2023-05-16 08:11:47

招聘信息暗藏玄机?亚马逊准备增加类ChatGPT电商搜索

2023-05-16 07:59:38

世界速递!三分之一功耗 RTX4000 SFF计算卡性能堪比3060Ti

2023-05-16 06:43:18

“北向互换通”正式启动 首日成交82.59亿元 前沿热点

2023-05-16 05:42:00

神武内丹神兽多少钱_神武真元丹多少级用的?

2023-05-16 03:44:38

豫a车牌和豫v车牌有什么区别_豫v和豫a是哪里的车牌?

2023-05-16 00:49:37

TOP STANDARDCORP(08510.HK)一季度营收370万港元

2023-05-15 22:51:19

葛雷瑟安全弹_关于葛雷瑟安全弹的简介

2023-05-15 21:52:45

瑞尼尔火山_关于瑞尼尔火山介绍

2023-05-15 21:14:15

全球热文:J-罗斯称科尔或去太阳 A-史密斯:不会 他和KD不来电&库里没退役

2023-05-15 20:07:28

焦点速讯:孞是什么意思怎么读视频(xs什么意思)

2023-05-15 19:31:08

家居周十条丨一季度家具类投诉量增长8.7%、前4月卖场销售额上涨超三成… 世界今头条

2023-05-15 18:44:57

全球头条:海济生物公司 海济生物

2023-05-15 17:59:45

2023年5月15日南京周大福今日金价多少钱一克-全球即时看

2023-05-15 17:42:58

环球要闻:关于第三十三届中国新闻奖自荐(他荐)参评作品的公示

2023-05-15 17:20:50

欧盟委员会预计2023年欧元区经济增长率为1.1% 世界热文

2023-05-15 16:36:01

太白县气象台发布大风蓝色预警【Ⅳ级/一般】【2023-05-15】

2023-05-15 16:07:12

黄国宇:黄金如期见顶下跌,反弹闭眼跑步空!

2023-05-15 15:22:16

短讯!各地积极“备战”麦收 “送检下乡”加强田间管理

2023-05-15 15:02:01

全球快讯:甘肃2023二建报名系统网址打印准考证

2023-05-15 14:34:08

应给“卖崽青蛙”合法经营的机会-天天短讯

2023-05-15 13:45:07

win7桌面图标消失了怎么恢复_win7电脑桌面图标不见了怎么恢复-天天滚动

2023-05-15 13:02:06

杭州冠益通贸易有限公司_关于杭州冠益通贸易有限公司概略

2023-05-15 12:03:11

睢阳区文化街道办事处:弘扬法治精神 共创平安环境 全球头条

2023-05-15 11:32:24

在职研究生证书有用吗 在职研究生证书_全球今日讯

2023-05-15 11:13:35

学业务、钻技术,拱墅城管开展停车技能大比武 资讯

2023-05-15 10:48:52

嗓子疼流鼻涕是流感吗?能用连花清瘟治疗吗?

2023-05-15 10:20:27

北京第十四届全民健身体育节启幕-全球速读

2023-05-15 10:06:39

执著怎么读_执著的含义

2023-05-15 08:56:10

形容灯火通明的词语(形容灯火通明)

2023-05-15 08:13:56

冷门关键词怎么做百度排名_怎么做百度排名|当前快报

2023-05-15 07:21:41

全球最资讯丨15岁西单大悦城追赶Z世代

2023-05-15 06:03:53

透视医圣 小说 天天视讯

2023-05-15 04:01:31

全球热议:发票增量情况说明_发票增量

2023-05-14 22:50:13

中文在线:公司已在有声书生产中应用AI主播 AI主播录制的有声书时长已超18万小时

2023-05-14 21:50:34

夯实责任 筑牢防线

2023-05-14 20:27:39

白银期货买一手要多少钱怎么计算(白银期货一手是多少需要多少钱)-当前快播

2023-05-14 19:02:56

《囚宠》_娈宠

2023-05-14 18:11:51

人教版一年级语文上册教案最新_人教版一年级语文上册教案 全球资讯

2023-05-14 17:16:10

世界今亮点!中天科技:子公司预中标12.09亿元欧洲高压海底电缆项目

2023-05-14 16:14:34

观察:中国式“坐月子”走红!外国网友直呼羡慕

2023-05-14 14:58:31

北京市地方标准公告2022年标字第21号(总第313号)

2023-05-14 13:04:56

当前热点-公摊率多少是符合标准的_公摊率

2023-05-14 11:57:39

2023年5月14日云南省绿豆芽批发价格行情|世界热门

2023-05-14 11:01:03

天天快报!菜鸟驿站客服电话_菜鸟驿站电话查询

2023-05-14 10:02:50

海南海鹏比邻湾房价为什么一直不跌?海鹏比邻湾楼盘优缺点~

2023-05-14 09:17:18

中央气象台:西北部分地区有扬沙或浮尘天气 华北黄淮江淮等地臭氧污染气象等级较高 世界视点

2023-05-14 08:04:54

下赛季473万美金球员选项!迪文:觉得这儿像家 愿意继续下去

2023-05-14 06:49:07

我很确信我愿意陪米兰成长但是我也很确定我不想陪皮...

2023-05-14 05:03:43

咸池桃花能遇正缘吗_咸池桃花是什么意思-环球速递

2023-05-14 02:53:29

全球速递!队报:因周六举行欧洲歌唱大赛,曼城客战埃弗顿被迫延期到周日

2023-05-13 23:26:41

我的快乐就是想你歌曲原唱简谱_我的快乐就是想你歌曲 每日视讯

2023-05-13 21:46:58

我国万吨级海上油气平台今天对接成功

2023-05-13 20:50:16

四川工商职业学院录取线-四川工商职业学院

2023-05-13 18:51:51

应得工资包括双倍工资的吗

2023-05-13 17:52:15

世界快播:五年级下册19课生字

2023-05-13 16:50:02

梁园区教育局在哪个位置_梁园区教育局|精彩看点

2023-05-13 15:46:59

今日关注:肾结石是怎么形成的原因_肾结石是怎么形成的

2023-05-13 14:56:45

全球视讯!AI大模型来袭,智能家居迎新拐点?

2023-05-13 13:53:08

世界通讯!2023外骨骼机器人行业报告:外骨骼机器人市场空间广阔

2023-05-13 12:20:49

全球快报:瑜伽契合法_关于瑜伽契合法介绍

2023-05-13 10:59:27

法治日报:虐猫取乐之病,得惩!得治!

2023-05-13 10:10:15

广西经贸高考分数线 广西南宁有哪些大学,录取分都是多少啊!(一本到高职... 天天热讯

2023-05-13 09:10:35

长身如玉 长身玉立_长身玉立不是形容女子的吗 为什么都被形容男人了

2023-05-13 08:45:40

【世界播资讯】qq飞车雷诺改装方案 雷诺改装方案

2023-05-13 08:01:53