ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java NIO(二)-----Buffer

2021-09-20 12:31:30  阅读:147  来源: 互联网

标签:Java NIO Buffer buffer ----- ByteBuffer 缓冲区 position


文章预览

前言

1、Java NIO简介

Java NIO(New IO 或 Non Blocking IO)是从 Java 1.4 版本开始引入的一个新的
IO API,可以替代标准的 Java IO API。NIO 支持面向缓冲区的、基于通道的 IO 操
作。NIO 将以更加高效的方式进行文件的读写操作。

Java NIO 由以下几个核心部分组成:

  • Channels
  • Buffers
  • Selectors
    虽然 Java NIO 中除此之外还有很多类和组件,但 ChannelBufferSelector 构成
    了核心的 API。其它组件,如 PipeFileLock,只不过是与三个核心组件共同使用的
    工具类。
    这一节详细介绍一下Channel,文章会持续更新

2、Buffer简介

Java NIO 中的 Buffer 用于和 NIO 通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。
在这里插入图片描述
缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成 NIO Buffer 对象,并提供了一组方法,用来方便的访问该块内存。缓冲区实际上是
一个容器对象,更直接的说,其实就是一个数组,在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,它也是写入到缓冲区中的;任何时候访问 NIO 中的数据,都是将它放到缓冲区中。而在面向流 I/O系统中,所有数据都是直接写入或者直接将数据读取到 Stream 对象中。在 NIO 中,所有的缓冲区类型都继承于抽象类 Buffer,最常用的就是 ByteBuffer,对于 Java 中的基本类型,基本都有一个具体 Buffer 类型与之相对应,它们之间的继承关系如下图所示:在这里插入图片描述

一、Buffer的基本用法

1.1、基本步骤

(1)写入数据到 Buffer
(2)调用 flip()方法
(3)从 Buffer 中读取数据
(4)调用 clear()方法或者 compact()方法
当向 buffer 写入数据时,buffer 会记录下写了多少数据。一旦要读取数据,需要通过flip()方法将 Buffer 从写模式切换到读模式。在读模式下,可以读取之前写入到 buffer的所有数据。一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用 clear()compact()方法。clear()方法会清空整个缓冲
区。compact()方法只会清除已经读过的数据。任何未读的数据都被到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。

1.2、使用 Buffer 的例子

  @Test
    public void buffer01() throws Exception {
        //FileChannel
        RandomAccessFile aFile =
                new RandomAccessFile("d:\\atguigu\\01.txt","rw");
        FileChannel channel = aFile.getChannel();

        //创建buffer,大小
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        //读
        int bytesRead = channel.read(buffer);

        while(bytesRead != -1) {
            //read模式
            buffer.flip();

            while(buffer.hasRemaining()) {
                System.out.println((char)buffer.get());
            }
            buffer.clear();
            bytesRead = channel.read(buffer);
        }

        aFile.close();
    }

1.3、 IntBuffer 的例子

 @Test
    public void buffer02() throws Exception {

        //创建buffer
        IntBuffer buffer = IntBuffer.allocate(8);

        //buffer放
        for (int i = 0; i < buffer.capacity(); i++) {
            int j = 2*(i+1);
            buffer.put(j);
        }

        //重置缓冲区
        buffer.flip();

        //获取
        while(buffer.hasRemaining()) {
            int value = buffer.get();
            System.out.println(value+" ");
        }
    }

1.4、Buffer 的 capacity、position 和 limit

为了理解 Buffer 的工作原理,需要熟悉它的三个属性:

  • Capacity
  • Position
  • limit

positionlimit 的含义取决于 Buffer 处在读模式还是写模式。不管 Buffer 处在什么模式,capacity 的含义总是一样的。
这里有一个关于 capacitypositionlimit 在读写模式中的说明
在这里插入图片描述
(1)capacity
作为一个内存块,Buffer 有一个固定的大小值,也叫“capacity”.你只能往里写capacity 个 byte、long,char 等类型。一旦 Buffer 满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。

(2)position

1)写数据到 Buffer 中时,position 表示写入数据的当前位置,position 的初始值为0。当一个 byte、long 等数据写到 Buffer 后, position 会向下移动到下一个可插入数据的 Buffer 单元。position 最大可为 capacity – 1(因为 position 的初始值为0).

2)读数据到 Buffer 中时,position 表示读入数据的当前位置,如 position=2 时表示已开始读入了 3 个 byte,或从第 3 个 byte 开始读取。通过 ByteBuffer.flip()切换到读模式时 position 会被重置为 0,当 Bufferposition 读入数据后,position 会下移到下一个可读入的数据 Buffer 单元。

(3)limit

1)写数据时,limit 表示可对 Buffer 最多写入多少个数据。写模式下,limit 等于Buffer 的 capacity。

2)读数据时,limit 表示 Buffer 里有多少可读数据(not null 的数据),因此能读到之前写入的所有数据(limit 被设置成已写数据的数量,这个值在写模式下就是position)。

1.5、Buffer 的类型

Java NIO 有以下 Buffer 类型

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

这些 Buffer 类型代表了不同的数据类型。换句话说,就是可以通过 char,short,int,long,float 或 double 类型来操作缓冲区中的字节。

二、案例Demo

2.1、缓冲区分片

ByteBuffer slice = buffer.slice();创建分片,即子缓冲区

@Test
    public void b01() {
        ByteBuffer buffer = ByteBuffer.allocate(10);

        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte)i);
        }

        //创建子缓冲区
        buffer.position(3);
        buffer.limit(7);
        ByteBuffer slice = buffer.slice();

        //改变子缓冲区内容
        for (int i = 0; i <slice.capacity() ; i++) {
            byte b = slice.get(i);
            b *=10;
            slice.put(i,b);
        }

        buffer.position(0);
        buffer.limit(buffer.capacity());

        while(buffer.remaining()>0) {
            System.out.println(buffer.get());
        }
    }

2.2、只读缓冲区

创建只读缓冲区

  ByteBuffer readonly = buffer.asReadOnlyBuffer();
//只读缓冲区
    @Test
    public void b02() {
        ByteBuffer buffer = ByteBuffer.allocate(10);

        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte)i);
        }

        //创建只读缓冲区
        ByteBuffer readonly = buffer.asReadOnlyBuffer();

        for (int i = 0; i < buffer.capacity(); i++) {
            byte b = buffer.get(i);
            b *=10;
            buffer.put(i,b);
        }

        readonly.position(0);
        readonly.limit(buffer.capacity());

        while (readonly.remaining()>0) {
            System.out.println(readonly.get());
        }
    }

2.3、直接缓冲区

创建直接缓冲区

  ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
@Test
    public void b03() throws Exception {
        String infile = "d:\\atguigu\\01.txt";
        FileInputStream fin = new FileInputStream(infile);
        FileChannel finChannel = fin.getChannel();

        String outfile = "d:\\atguigu\\02.txt";
        FileOutputStream fout = new FileOutputStream(outfile);
        FileChannel foutChannel = fout.getChannel();

        //创建直接缓冲区
        ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

        while (true) {
            buffer.clear();
            int r = finChannel.read(buffer);
            if(r == -1) {
                break;
            }
            buffer.flip();
            foutChannel.write(buffer);
        }
    }

2.4、内存映射文件io

 @Test
     public void b04() throws Exception {
         RandomAccessFile raf = new RandomAccessFile("d:\\atguigu\\01.txt", "rw");
         FileChannel fc = raf.getChannel();
         MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, start, size);

         mbb.put(0, (byte) 97);
         mbb.put(1023, (byte) 122);
         raf.close();
     }

标签:Java,NIO,Buffer,buffer,-----,ByteBuffer,缓冲区,position
来源: https://blog.csdn.net/niulinbiao/article/details/120389580

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有