java NIO Buffer

2 篇文章 0 订阅

1. 简介

Java NIO 中的 Buffer 用于和 NIO 通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的。

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

2. Buffer的capacity,position和limit

对buffer的操作核心就是对position和limit指针位置的操作。
capacity,position和limit结构图
capacity

作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空才能继续写数据往里写数据。

position

当你写数据到Buffer中时,position表示当前的位置。初始的position值为0,当写入/读取一个数据的时候position会+1。position最大可为capacity – 1。
调用flip()切换读模式的时候,position会重置为0.

limit

在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。
当切换Buffer到读模式时, limit表示你最多能读到多少数据。limit会被设置成之前的position值,换句话说,你能读到之前写入的所有数据。

3. Buffer的类型

Java NIO 有以下Buffer类型

ByteBuffer
MappedByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer

4. Buffer的基本用法

标准流程:
1 . 创建buffer,写入数据到Buffer
2 .调用flip()方法,将limit = position ,position = 0,切换读模式
3 .从Buffer中读取数据
4 .读取完成后调用clear()方法或者compact()方法,是指针复位,以备下次读取。

注意事项:
1 . flip()方法不能连续调用多次,否则指针会混乱
2 . clear()方法并不能真正清除数据,只是将指针复位,待下次写入数据时就可以覆盖原数据。如果需要连续写入,在第一次写入完成后调用mark()标记位置,然后在需要再次写入的时候调用reset()复位。
3 . Channel
read()方法是写入buffer,写入前应该是刚创建的buffer或者调用一次clear;
write()方法是读取buffer。读取前应该调用一次flip();

示例代码:

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
//create buffer with capacity of 48 bytes
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf); //read into buffer.
while (bytesRead != -1) {
  //切换读模式
  buf.flip();  //make buffer ready for read
  while(buf.hasRemaining()){
      System.out.print((char) buf.get()); // read 1 byte at a time
  }
}
buf.clear();
aFile.close();

5.Buffer实用工具类

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Calendar;

/**
 * @author: zonglin_wu
 * @Date: 2018/7/25 19:42
 * @Description:
 */
public class ByteBufferUtil {

    public static byte[] readByte(ByteBuffer byteBuffer){
        byte[] b = null;
        //为读者做准备,切换读模式
        byteBuffer.flip();
        b = new byte[byteBuffer.limit()];
        byteBuffer.get(b);
        //清楚标记位
        byteBuffer.clear();
        return b;
    }

    /**
     *  读取byteBuffer数据,在方法调用之前不能调用filp()或者clear()之类的操作指针的函数
     * @param byteBuffer
     * @return
     */
    public static String readString(ByteBuffer byteBuffer){
        try {
            byte[] b = readByte(byteBuffer);
            String s = new String(b, "UTF-8");
            return s;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 一次性写入,每次从头写入,写入完成后切换读模式。
     * @param byteBuffer
     * @param data
     */
    public static void onceWrite(ByteBuffer byteBuffer,String data){
        try {
            //写之前指针复位
            byteBuffer.clear();
            byteBuffer.put(data.getBytes("utf-8"));
            byteBuffer.flip();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 可以进行多次写入,指针不复位
     * @param byteBuffer
     * @param data
     */
    public static void write(ByteBuffer byteBuffer,String data){
        try {
            byteBuffer.put(data.getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 可以进行多次写入,指针不复位
     * @param data
     */
    public static ByteBuffer write(String data){
        ByteBuffer byteBuffer = ByteBuffer.allocate(data.getBytes().length);
        try {
            byteBuffer.put(data.getBytes("utf-8"));
            return byteBuffer;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 一次性写入,每次从头写入,写入完成后切换读模式。
     * @param data
     */
    public static ByteBuffer onceWrite(String data){
        ByteBuffer byteBuffer = ByteBuffer.allocate(data.getBytes().length);
        try {
            byteBuffer.put(data.getBytes("utf-8"));
            byteBuffer.flip();
            return byteBuffer;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值