Java NIO - Buffer

一、Buffer基础知识

JAVA NIO中的Buffer用于和NIO通道进行交互,数据从通道读入缓存区,从缓存区写入通道。

缓冲区本质上是一块可以写入数据,也可以读出数据的内存,这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的调用该块内存。

二、Buffer的基本用法

1、使用Buffer读写数据一般有四种个步骤:

  1. 写入数据到Buffer,Buffer会记录写入了多少数据。
  2. 调用flip()方法,将Buffer从写模式转换为读模式。
  3. 从Buffer中读取数据。
  4. 调用clear()方法或compact()方法。clear()方法会清空缓存区所有的数据,compact()方法只会清除已经读取的数据。

任何未读的数据都会被放到缓存区的起始处,新写入的数据放到缓存区未读取数据的后面。



2、buffer的capacity、position和limit

理解Buffer的工作原理,需要熟悉它的三个属性:capacity、position、limit。

position和limit的含义取决于Buffer处于读模式还是写模式,但capacity的含义一直不变。
capacity:作为一个内存块,Buffer有一个固定的大小,”capacity”。
limit:Buffer在不同的模式下,可以写入或读取数据的多少。但一般情况下,limit都会被设置为之前position的值。
position:当你写入或读取Buffer时,position表示当前的位置,每一次Buffer转换模式时,position都会被初始化为0,position的最大值为capacity-1。

准确理解capacity、position、limit所代表的意义对于理解Buffer有很大的帮助。



3、Buffer的类型

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

这里包含了常见的数据类型,也有map类型的数据。


4、Buffer的分配

要想获得一个Buffef对象,首先要对对象进行分配,每一个Buffer类都有一个allocate()方法,用于分配不同的字节给Buffer。

ByteBuffer buf = ByteBuffer.allocate(1024);//创建一个Buffer,状态为写入状态


5、flip()方法

flip()方法将Buffer从写模式转换为读模式。
调用flip()方法会将position设置为0,并将limit设置为之前position的值。

buf.flip();//反转Buffer,将写入状态转换为写出状态


6、rewind()方法

rewind()方法将position设置为0,所以可以重读Buffer中的所有数据,并且返回一个Buffer。

 out.write(buf);    // Buffer中写入数据
 buf.rewind();      // 重绕缓冲区Buffer 
 buf.get(array);    // Buffer中的数据被替换到array


7、clear()方法和compact()方法

当读取完Buffer中的数据,需要让Buffer准备好再次被写入,可以调用clear()和compact()方法实现。

clear()方法会将position被设置为0,limit被设置为capacity的值。此时Buffer被清空,然后Buffer中的数据并未清除,只是告诉我们该从哪里写入数据。

compact()方法会将所有未读的数据拷贝到Buffer起始处,然后将position设到最后一个未读元素的后面,limit依旧被设置为capacity,现在Buffer写入数据就不会覆盖未读的数据了。

buf.clear();//将Buffer清空,以便下次写入

当你读过源码你就会知道,此方法不能实际清除缓冲区中的数据,但从名称来看它似乎能够这样做,这样命名是因为它多数情况下确实是在清除数据时使用。



8、mark()方法和reset()方法

调用mark()方法可以标记一个特定的position,之后可以通过reset()方法恢复到这个position。

两者的返回值都为Buffer,而且被标记之前的position并不会被丢弃。



9、equals()和compareTo()方法

使用equals()和conoareTo()比较两个Buffer对象

对于equals()方法,当满足下列条件时,两个Buffer相等:

  1. 相同的类型。
  2. Buffer中剩余的byte、char等的个数相等。
  3. Buffer中所有的剩余的byte、char等都相同。
  4. 返回值:相同时为true,其余为false。

equals()只比较Buffer的一部分,不是每一个在它的元素都比较,实际上,它只比较Buffer中剩余的元素。

compareTo()只比较Buffer的剩余元素byte、char
若满足下列条件,认为一个Buffer小于另一个Buffer:

  1. 第一个不相等的元素小于另外一个Buffer中对应的元素。
  2. 比较两个字节缓冲区的方法是按字典顺序比较它们的剩余元素序列,而不考虑每个序列在其对应缓冲区中的起始位置。
  3. 返回值:正整数、负整数和零。

注:剩余元素是从position到limit之间的元素。


三、Demo

package com.vgbh;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class ChannelDemo {

    public void readFromChannelFile () {
        try {
            RandomAccessFile file = new RandomAccessFile("F:/WorkSpace/TestBook.txt", "rw");//IO的获取文件类
            FileChannel fileChannel = file.getChannel();

            ByteBuffer buf = ByteBuffer.allocate(1024);//创建一个Buffer,状态为写入状态

            int byteReads = fileChannel.read(buf);//当前buf中的数据长度

            while (byteReads != -1) {
                System.out.println("ssss   " + byteReads + "   ssss");
                buf.flip();//反转Buffer,将写入状态转换为写出状态

                while (buf.hasRemaining()) {
                    System.out.print((char)buf.get());//获取buf中的数据,将int转换为char,在buf写完后会自动转换为写入状态
                }

                buf.clear();//将Buffer清空,以便下次写入

                byteReads = fileChannel.read(buf);//重新写入新的数据
            }

            file.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

上边的代码只是一个小Demo,有兴趣的可以将其应用到实践中去。
推荐大家可以去看看Java的API文档,有很大的帮助。

有问题的可以联系我的邮箱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vgbh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值