Java NIO使用的数据结构不是普通的byte[],而是类似ByteBuffer的类。ByteBuffer使用起来与byte[]有很大不同,下面主要是自己学习到的一些使用方法。
ByteBuffer同时可以读写,一开始理解有点困难,建议按照推荐的操作步骤来使用ByteBuffer。即
- Channel#read(ByteBuffer)或者ByteBuffer#put方法,往ByteBuffer里面写入数据
- ByteBuffer#flip
- Channel#write(ByteBuffer)或者ByteBuffer#get方法,从ByteBuffer里面读取数据
- ByteBuffer#clear, ByteBuffer#compact
读写模式通过不同的API来切换,一般情况下,按照上面这个顺序使用ByteBuffer就可以。不过要正确理解和使用ByteBuffer,需要对ByteBuffer的内部有所了解。
ByteBuffer主要有三个位置指针(不是C/C++的pointer)
- position,当前位置
- limit,当前模式下的位置限制
- capacity,分配时确定的空间大小
capacity因为一开始就被确定了,最容易理解。剩下两个位置指针需要配合ByteBuffer的“读写模式”来理解。
- ByteBuffer被分配之后,默认是“写模式”,因为刚分配的空间你读取是没有意义的。这时position为0,limit为capacity的值。假设代码中执行了一些写入操作,每次写入都会增加position。
- flip切换读写模式,position为0,即你写入的第一个byte的位置,limit变成你写入数据的最后一个byte后面的位置。
- 接下来你可以从ByteBuffer中读取数据了,每次读取增加position。
- 读取完毕之后,可以复用这个ByteBuffer,调用clear的话,position重置为0,limit设置为capacity,即回到写模式的初始状态。调用compact的话,你没有读取的数据会向前移动(System.arrayCopy),position设置为这些数据末尾之后的位置,limit设置为capacity。
用代码来测试一下