java nio中的ByteBuffer扩展

这篇具有很好参考价值的文章主要介绍了java nio中的ByteBuffer扩展。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在jdk1.4之前对于输入输出只能使用InPutStream和outPutSream这类传统io模型,在jdk1.4之后新增了nio,什么是nio?nio是new input/output 的简称,nio的效率要比传统io效率高,主要原因就是nio利用了系统底层的零拷贝技术和多路复用技术。

NIO核心知识

NIO有三个核心概念
1、Channal通道
2、Buffer缓冲
3、Selector选择器

以上三者之间的关系是,一个线程拥有一个selector选择器,一个selector选择器管理多个channel通道,每个channel通道具有一个Buffer缓冲。为了更好的理解nio这三者之间的关系。举一个实际生活中遇到的例子。公司一般每年都会提供免费的体检,一般都是和爱康国宾合作的,去体检了几次发现一个有趣的事情:
1、客户很多、体检项目也很多。但是客户不知道自己应该去哪个房间体检。
2、体检中心提供一个中转中心,中转中心四周都是体检房间,所有的人在每项体检后都要经过这个中转中心。
3、每个体检者手里都要握着一个体检单。体检单上会有自己的体检项目。
4、中转中心有一个工作人员(引导员),每个体检人员来到中转中心,引导员会结合体检房间的空闲情况和体检者的体检单来指定具体要去的体检场所。
5、体检速度快,不会产生太长的队伍,比较高效的方式。
那这个这里里面有几个角色完全可以对应nio中的三个概念,分别是,引导员=selector, 体检者手上的体检单=Buffer, 每个体检者=channel;

ByteBuffer

ByteBuffer是Buffer的一个子类,实现方式类似byte[], 该类有个重要的概念就是指针,指针标志的位置代表下次操作的位置。
ByteBuffer分为读模式和写模式,当然了这种称谓都是人们习惯性的称呼,其实只是指针指向的区别,比如读模式指针指向数组下标为0的位置,写模式指针指向数组最后一位。在实际使用中一个byteBuffer可能需要被反复读取多次,于是byteBuffer提供了mark()方法,mark方法标记的下标供reset方法使用。如果当前byteBuffer中存储的是[a,b,c,d,e]这五个字符,读取的时候读取到c的时候调用了mark()方法添加了标记,那么当读取到e时,又想从标记的地方重新读取时,只需要调用reset()即可将指针指向c的位置,ByteBuffer提供的方法虽然很好,但是在日常使用的时候还是不太方便,比如在b处打了标记,当读取到c时又打了标记,目的时要从c处重新读取一遍,然后再从b处重新读取一遍,这是byteBuffer就显得有些不太好使了。所以笔者写了一个扩展byteBuffer的类。

代码如下:

package pers.cz.tools;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 * @program: Reids
 * @description: 扩展ByteBuffer,提供多次标记的功能。
 * @author: Cheng Zhi
 * @create: 2023-04-13 20:23
 **/
public class JefByteBuffer {

    /**
     * 保存所有的标记点
     */
    private int[] markPocket = new int[16];

    ByteBuffer byteBuffer;

    private int index = 0;

    public JefByteBuffer(int capacity, boolean isUseLocalMem) {
        if (isUseLocalMem) {
            byteBuffer = ByteBuffer.allocateDirect(capacity);
        } else {
            byteBuffer =  ByteBuffer.allocate(capacity);
        }
    }

    public JefByteBuffer(ByteBuffer byteBuffer) {
        this.byteBuffer = byteBuffer;
    }

    /**
     * 切换模式
     */
    public Buffer flip() {
       return byteBuffer.flip();
    }

    public char read() {
        return (char) byteBuffer.get();
    }

    public void unread() {
        int position = byteBuffer.position();
        byteBuffer.position(position - 1);
    }
    public byte get() {
        return byteBuffer.get();
    }

    public void put(byte[] src) {
        byteBuffer.put(src);
    }

    public void put(byte bi) {
        byteBuffer.put(bi);
    }

    public void clear() {
        byteBuffer.clear();
    }

    public boolean isEnd() {

        int current = byteBuffer.position();
        int end = byteBuffer.limit();
        if (current == end) {
            return true;
        }

        return false;
    }
    /**
     * 打标记
     */
    public void mark() {
        int mark = byteBuffer.position();
        ensureCapacityInternal();
        markPocket[index] = mark;
        index ++;
    }

    /**
     * 去除标记
     */
    public void unmark() {
        index --;
        markPocket[index] = 0;
    }

    /**
     * 重置
     */
    public void reset() {
        index --;
        if (index < 0) {
            return;
        }
        int mark = markPocket[index];
        if (mark < 0) {
            return;
        }
        byteBuffer.position(mark);
    }

    /**
     * 为markPocket扩容
     */
    private void ensureCapacityInternal() {

        int oldCapacity = markPocket.length;
        if (index >= oldCapacity) {
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            // minCapacity is usually close to size, so this is a win:
            markPocket = Arrays.copyOf(markPocket, newCapacity);
        }
    }
}

使用方式:

public static void test2() {
        JefByteBuffer jefByteBuffer = new JefByteBuffer(100);
        jefByteBuffer.put(new byte[] {'1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'});
        jefByteBuffer.flip();
        for (int i=1; i<21; i++) {

            if (i == 1) {
                jefByteBuffer.mark();
            }
            if (i == 3) {
                jefByteBuffer.mark();
            }
            if (i == 5) {
                jefByteBuffer.mark();
            }

            if (i == 7) {
                jefByteBuffer.mark();
            }

            if (i == 9) {
                jefByteBuffer.mark();
            }

            if (i == 10) {
                jefByteBuffer.unmark();
            }
            if (i == 11) {
                //jefByteBuffer.unmark();
                // 这里将回到i=7的标记点
                jefByteBuffer.reset();
            }

/*            if (i ==8) {
                jefByteBuffer.reset();
            }*/
            char b = (char) jefByteBuffer.read();
            jefByteBuffer.unread();
            System.out.println(b);
        }

    }

这样在使用byteBuffer的时候就可以灵活的读取,方法名更是见名知意,比如read读取了一个字节之后,调用unread后还可以重新读取。文章来源地址https://www.toymoban.com/news/detail-415538.html

到了这里,关于java nio中的ByteBuffer扩展的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零开始学习Netty - 学习笔记 - NIO基础 - ByteBuffer: 简介和基本操作

    1.1. Channel Buffer Channel 在Java NIO(New I/O)中,“Channel”(通道)是一个重要的概念,用于 在非阻塞I/O操作中进行数据的传输 。Java NIO提供了一种更为灵活和高效的I/O处理方式,相比于传统的I/O,它具有更好的性能和可扩展性。 常见的Java NIO中的通道类型: FileChannel(文件通道

    2024年02月20日
    浏览(48)
  • Java——JDK1.8新特性

    目录 一、Lambda 表达式 (一)Lambda 表达式语法 (二)类型推断 二、函数式接口 (一)自定义函数式接口 (二)作为参数传递Lambda 表达式 (三)Java 内置四大核心函数式接口 三、方法引用 四、Stream API (一)什么是Stream? (二)Stream 的操作三个步骤 (三)创建流的四种方

    2024年02月07日
    浏览(87)
  • Java中jdk1.8和jdk17相互切换

    之前做Java项目时一直用的是jdk1.8,现在想下载另一个jdk版本17,并且在之后的使用中可以进行相互切换,我将jdk切换时所遇到的问题记录下来并分享出来供大家参考。 环境变量配置如下: 步骤1 步骤2 (注:@MAVEN_HOME%bin;是配置maven时的环境变量,如果没有安装maven就不用管)

    2024年02月03日
    浏览(64)
  • java jdk1.8下载与安装

    官网下载地址:Java Downloads | Oracle 打开官网链接,下滑至Java 8模块,选取自己电脑适合的版本点击下载 1.找到我们下载的安装包,双击运行 2.点击下一步 3.点击更改,修改安装目录   4.选择合适的安装位置,点击确定   5.点击下一步   6.弹出jre的安装选项,点击更改,修改

    2024年02月08日
    浏览(55)
  • java jdk1.8.0_221 安装步骤

    一、下载jdk Oracle JDK下载官网https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html下载jdk1.8.0_221. 需要注册账号登陆才能下载。 下载完成,双击jdk-8u221-windows-x64.exe,进行安装。 二、安装jdk 安装前准备工作,D盘新建文件夹JAVA,在JAVA文件夹中新建两个文件夹:jdk和

    2024年02月06日
    浏览(59)
  • [Java]静态代理、动态代理(基于JDK1.8)

    【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18002823 出自【进步*于辰的博客】 参考笔记一,P83;笔记二,P75.4。 目录 1、概述 2、静态代理的两种形式 2.1 面向接口 2.2 面向继承 3、动态代理的两种形式 3.1 JDK动态代理

    2024年03月09日
    浏览(39)
  • 【Java基础】JDK8.0(JDK1.8)版本的下载与安装

    JDK(Java SE Development Kits)是Java程序员使用的开发环境,包含JRE和开发工具集。 JRE(Java Runtime Environment) :是Java程序的运行时环境,包含JVM和运行时所需要的核心类库。 官网地址:https://www.oracle.com/cn/java/technologies/javase/javase8u211-later-archive-downloads.html 链接:https://pan.baidu.com/

    2024年02月13日
    浏览(68)
  • 【Java】jdk1.8 Java代理模式,Jdk动态代理讲解(非常详细,附带class文件)

       📝个人主页:哈__ 期待您的关注  想要学代理模式,我们就要先弄清一个概念 “什么是代理”? 在我们的现实生活中,你或许不少听过关于代理的名词,如:代理商。那什么又叫做代理商?让我一个词来形容就是 中间商。 举个例子,在你买二手房的时候,你一般不会直

    2024年04月15日
    浏览(45)
  • Windows11配置Java8开发环境 - JDK1.8

    1、下载JDK 我们要下载的是Oracle版本的JDK,我们首先进入Oracle的官网的Java下载页面:https://www.oracle.com/cn/java/technologies/downloads/ 一直往下滑 ,找到 Java8 —点击 Windows (如果你是其他系统选择你对应的系统即可)— 在下方根据你的电脑系统类型选择对应的X86或X64然后点击下载

    2024年02月10日
    浏览(50)
  • 【Java】JDK1.8 HashMap源码,put源码详细讲解

       📝个人主页:哈__ 期待您的关注  在Java中,HashMap结构是被经常使用的,在面试当中也是经常会被问到的。这篇文章我给大家分享一下我对于HashMap结构源码的理解。 HashMap的存储与一般的数组不同,HashMap的每一个元素存储的并不是一个值,而是一个引用类型的Node结点,这

    2024年04月13日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包