缓冲区基础
缓冲区是对基本数据元素数组的封装对象,Buffer类及其专有的子类提供了用于处理数据缓冲区的API
缓冲区不是多线程安全的,多线程同时存取时,需要同步
属性
- Capacity(容量): 缓冲区大小,创建时设定,不能更改
- Limit(上界): 缓冲区现存元素数量
- Position(位置): 下一个要被读或写的元素索引,位置会自动由相应的get()和put()函数更新
- Mark(标记): 一个备忘位置,调用mark()来设定mark=position,调用reset()设定position=mark
- 关系: 0 <= mark <= position <= limit <= capacity
缓冲区API
public abstract class Buffer { public final int capacity()//容量 public final int position()//返回下一个将要被读写的元素索引 public final Buffer position (int newPosition)//设置下一个被读写元素的索引 public final int limit()//返回缓冲区上界 public final Buffer limit (int newLimit)//设置缓冲区上界 public final Buffer mark()//设置标记mark=position public final Buffer reset()//重置读写位置position=mark public final Buffer clear()//重置为0,即limit=capacity,position=0 public final Buffer flip()//翻转,将添加元素状态翻转成读取元素状态(相当于limit = position,然后position = 0然后开始读取写入的元素) public final Buffer rewind()//position=0,mark=-1 public final int remaining()//返回剩余可读元素数量,当前位置到上界还剩余的元素数量 public final boolean hasRemaining()//是否有剩余可读元素,即是否到达上界(limit) public abstract boolean isReadOnly();//是否只读 }
存取
public abstract class ByteBuffer extends Buffer implements Comparable{ public abstract byte get();//取position位置 public abstract byte get (int index);//取index位置 public abstract ByteBuffer put (byte b);//存position位置开始 public abstract ByteBuffer put (int index, byte b);//存index位置开始 //...批量存取 }
翻转
- filp() : 翻转,将继续添加元素状态翻转成一个准备读取元素状态
- 如果已经写入缓冲区,此时想要读取缓冲区内容,我们需将limit设置为当前位置position,然后将position重置为0,此时使用get()即可读取等价于: buffer.limit(buffer.position()).position(0)
- 缓冲区翻转两次,实际可读取大小会变成0(limit=0,position=0)
释放
- clear()将缓冲区重置为0,仅仅是limit = capacity,position=0,没有改变缓冲区内的任何数据元素
压缩/比较
public abstract class ByteBuffer extends Buffer implements Comparable{ public abstract ByteBuffer compact();//将未读元素移动到数组首 public boolean equals (Object ob)//比较每个缓冲区剩余的内容是否相同(对象类型必须相同) public int compareTo (Object ob)//以字典顺序比较,可以比较大小 }
创建缓冲区
CharBuffer,IntBuffer,DoubleBuffer,ShortBuffer,LongBuffer,FloatBuffer,ByteBuffer七种缓冲区创建方式相同,(MappedByteBuffer特殊)
//以CharBuffer为例 public abstract class CharBuffer extends Buffer implements CharSequence, Comparable{ public static CharBuffer allocate (int capacity)//分配一个固定容量的缓冲区 public static CharBuffer wrap (char [] array)//使用自定义的数组作为缓冲区 public static CharBuffer wrap (char [] array, int offset,int length)//使用自定义数组作为缓冲区,并设置初始化位置(position)和长度(limit-position) public final boolean hasArray()//是否存在底层数组(allocate或wrap()创建的间接缓冲区底层都是数组) public final char [] array()//获取缓冲区底层数组(hasArray()返回false时不要使用,会抛异常) public final int arrayOffset()//返回缓冲区数据在数组中存储的开始位置偏移量 //特有的 public static CharBuffer wrap (CharSequence csq)//通过可读字符流创建缓冲区(实现Charsequence接口的类: String,StringBuffer等) public static CharBuffer wrap (CharSequence csq, int start,int end) //通过字符流的子序列创建缓冲区 }
复制缓冲区
public abstract class CharBuffer extends Buffer implements CharSequence, Comparable{ //创建一个与原始缓冲区相似的新缓冲区,两个缓冲区共享数据元素,拥有同样容量,(相当于底层共用一个数组) //但拥有各自的position,limit,mark属性,一个缓冲区改变会反映到另一个缓冲区上,会继承只读或直接缓冲区属性 public abstract CharBuffer duplicate(); public abstract CharBuffer asReadOnlyBuffer();//同duplicate,不同的是改缓冲区只读,不能使用put() public abstract CharBuffer slice(); //分割缓冲区,从源缓冲区position位置开始到limit位置结束创建一个新缓冲区 //新缓冲区与原始缓冲区共享元素子序列,会继承只读和直接属性 }
字节缓冲区
字节顺序:
- BIG_ENDIAN(大端字节顺序: 数字高->低位,存储内存地址低->高) , LITTLE_ENDIAN(小端字节顺序,Intel处理器使用小端字节顺序)
public final class ByteOrder{ public static final ByteOrder BIG_ENDIAN//大端字节顺序 public static final ByteOrder LITTLE_ENDIAN//小端字节顺序 public static ByteOrder nativeOrder()//获取本地字节顺序 }
public abstract class ByteBuffer extends Buffer implements Comparable{ public final ByteOrder order()//查询字节顺序 public final ByteBuffer order (ByteOrder bo)//设置字节顺序 }
- BIG_ENDIAN(大端字节顺序: 数字高->低位,存储内存地址低->高) , LITTLE_ENDIAN(小端字节顺序,Intel处理器使用小端字节顺序)
直接缓冲区
- 直接缓冲区被用于与通道和固有I/O例程交互,它们通过使用固有代码来告诉操作系统直接释放或填充内存区域
public abstract class ByteBuffer extends Buffer implements Comparable{ public static ByteBuffer allocateDirect (int capacity)//分配直接字节缓冲区 public abstract boolean isDirect();//是否直接缓冲区,如果底层是基于直接字节缓冲区的包装(wrap)缓冲区则也是true }
- 直接缓冲区被用于与通道和固有I/O例程交互,它们通过使用固有代码来告诉操作系统直接释放或填充内存区域
视图缓冲区
- 视图缓冲区对象维护了自己的属性丶容量丶位置丶上界和标记,但是和原来的缓冲区共享数据元素
//基于ByteBuffer缓冲区创建其视图缓冲区 public abstract class ByteBuffer extends Buffer implements Comparable{ public abstract CharBuffer asCharBuffer(); public abstract ShortBuffer asShortBuffer(); public abstract IntBuffer asIntBuffer(); public abstract LongBuffer asLongBuffer(); public abstract FloatBuffer asFloatBuffer(); public abstract DoubleBuffer asDoubleBuffer(); }
- 视图缓冲区对象维护了自己的属性丶容量丶位置丶上界和标记,但是和原来的缓冲区共享数据元素
数据元素视图
- ByteBuffer类提供了以多字节数据类型的形式存取byte数据组
public abstract class ByteBuffer extends Buffer implements Comparable { public abstract char getChar(); public abstract char getChar (int index);//从index位置开始取2字节char值 public abstract int getInt();//从position位置开始取4字节int值 public abstract int getInt (int index); //...等等 public abstract ByteBuffer putFloat (float value); public abstract ByteBuffer putFloat (int index, float value); public abstract ByteBuffer putDouble (double value); public abstract ByteBuffer putDouble (int index, double value); }
- ByteBuffer类提供了以多字节数据类型的形式存取byte数据组
内存映射缓冲区
- 映射缓冲区是通过内存映射来存取文件中的数据元素的字节缓冲区,映射缓冲区通常是直接存取内存的,只能通过FileChannel类创建,用法和直接缓冲区类似,但是MappedByteBuffer对象可以处理独立与文件存取形式的许多特定字符