Java NIO之Buffer
Java传统的I/O模型是面向单个字节的,它将输入输出抽象为字节流或字符流。这种单个字节的读取或写入模型的效率比较低,而且不符合操作系统的I/O特点。操作系统的IO是面向字节块的,通常是直接从磁盘中读取一块数据到内存或写入一块数据到磁盘。Java NIO提供了缓冲区来实现字节块的读写。
Buffer内部管理着一个数组,数据存放在数组中。Buffer作为数据的载体,Java程序在使用NIO时都会通过Buffer与外界进行通信。
一.缓冲区的类别
如上图所示,除了boolean类型外,Java为其他七种基本类型提供了相应的Buffer。这七种Buffer中,ByteBuffer是最基本的Buffer,其他的类的Buffer可以通过ByteBuffer转换得到。而且在使用通道对外传输数据时,要求必须是ByteBuffer。
二.缓冲区的四种属性
1.capacity
容量表示缓冲的大小,其实就是缓冲区内部数组的大小。
2.position
位置表示缓冲区中当前可读写位置。当调用get()、put()等函数进行读写时,会自动更新position。
3.limit
limit表示缓冲区中可用元素的大小。当写缓冲区时,limit等于capacity,表示整个缓冲区都可写。当读缓冲区时,limit是缓冲区中已有元素的大小,表示读取缓冲区的位置不能超过limit。
4.mark
mark是备忘位置,可以暂时存储position,以便position改变后可以恢复到原来的位置。
三、Buffer的API
- capacity()返回缓冲区的容量。
- position()返回当前的位置,而position(int)可以设置新的位置,如果给定的参数超过了limit或小于0,会抛出IllegalArgumentException,另外position小于mark,会把mark置为-1,因此在缓冲区使用过程中会一直保持mark<=position<=limit。
- limit()直接返回limit属性值。
- limit(int)会设置新的limit值,如果新的limit超过了capacity会抛出IllegalArgumentException,如果小于position,则会把position设置为limit,如果小于mark,则mark设为无效值-1。
- mark()方法会把当前position记录到mark属性,而reset()方法会把position值设置为mark。
- clear()将Buffer置为初始状态,position置为0,limit设置为capacity,mark设置为-1。通常在写入数据之前需要调用该方法。
- flip()表面意思是“翻转”,生动的描述了Buffer从写状态进入读状态,该方法会将limit设置为position,同时position设置为0,mark置为-1。
- rewind()方法将position设置为0,以便能重头开始读写数据。
- remaining()返回缓冲区剩余元素的大小,limit-position。hashRemaining()表示缓冲区是否还有剩余元素。
四.Buffer的读写
ByteBuffer的读数据API如下:
Buffer类没有读写相关的API,其各个子类中才有相应的API,这是因为Buffer的子类存储的类型各不相同,不能作为公共API放到Buffer中。在ByteBuffer中有四种方法可以读取数据:
- get()从当前位置获取一个字节,并将position移动到下一个位置。