遵循:BY-SA
署名-相同方式共享 4.0协议
作者:谭东
时间:2016年10月30日
环境:Windows 7
ByteBuffer也许很多人不常用,其实它是最常用的缓冲区,可以负责缓冲存储一段数据,供数据的写入和读取。ByteBuffer是NIO里用得最多的Buffer。
ByteBuffer最核心的方法是put(byte)和get()。分别是往ByteBuffer里写一个字节,和读一个字节。
值得注意的是,ByteBuffer的读写模式是分开的,正常的应用场景是:往ByteBuffer里写一些数据,然后flip(),然后再读出来。
我们先来看看ByteBuffer的几个主要的方法。
1、如何创建一个ByteBuffer?
可以通过,ByteBuffer buffer=ByteBuffer.allocate(256);创建或者 ByteBuffer buffer=ByteBuffer.wrap(byteArray);这里的byteArray可以包含了数据,相当于写入了数据到缓冲区。
2、如何写入数据到ByteBuffer?
可以通过ByteBuffer buffer=ByteBuffer.wrap(byteArray);写入数据或者buffer.put(bytes);方法写入数据。
3、如何把数据准备为数据传出状态?
调用buffer.flip();
4、如何清除缓冲区?
buffer.clear(); 这个方法实际上也不会改变缓冲区的数据,而只是简单的重置了缓冲区的主要索引值,不必为了每次读写都创建新的缓冲区,那样做会降低性能。相反,要重用现在的缓冲区,在再次读取之前要清除缓冲区。
5、如何读取缓冲数据?
调用buffer.get(bytes);
接下来用图片展示看下ByteBuffer的一些属性和方法。
byte[] buff
buff即内部用于缓存的数组。
position
当前读取的位置。
mark
为某一读过的位置做标记,便于某些时候回退到该位置。
capacity
初始化时候的容量。
limit
读写的上限,limit<=capacity。
写模式下,往buffer里写一个字节,并把postion移动一位。写模式下,一般limit与capacity相等。
写完数据,需要开始读的时候,将postion复位到0,并将limit设为当前postion。
从buffer里读一个字节,并把postion移动一位。上限是limit,即写入数据的最后位置。
将position置为0,并不清除buffer内容。
mark相关的方法主要是mark()(标记)和reset()(回到标记)。
给大家两个例子:
这个代码是针对有数据的ByteBuffer,我们读取出来数据,写成文件的操作。之前用来做H264写文件用到的。仅供参考。
@Override public void onFrameAvailable(Object o) { ImgBufFrame imgBufFram = (ImgBufFrame) o; byte[] bytes = new byte[imgBufFram.buf.limit()]; imgBufFram.buf.get(bytes); try { if (!write) { fout = new FileOutputStream(MyConfiguration.VIDEO_PATH + "/video.h264", true); write = true; } fout.write(bytes); } catch (IOException e) { e.printStackTrace(); } }
下面这个例子是针对有数据的ByteBuffer,我们给他再写入一点头文件数据,之前用来做AAC裸流缺少ADTS头文件7位字节信息时,为AAC的每个缓冲加入前7位的ADTS头信息的。仅供参考。
@Override public void onFrameAvailable(Object o) { AudioBufFrame audioBufFrame = (AudioBufFrame) o; int outBufferSize = audioBufFrame.buf.limit() + 7; byte[] aacBytes = new byte[outBufferSize]; try { if (!write) { fout = new FileOutputStream(MyConfiguration.VIDEO_PATH + "/audio.aac"); write = true; } addADTStoPacket(aacBytes, outBufferSize); audioBufFrame.buf.get(aacBytes, 7, audioBufFrame.buf.limit()); fout.write(aacBytes); } catch (IOException e) { e.printStackTrace(); } }
/** * 添加ADTS头 * * @param packet * @param packetLen */ private void addADTStoPacket(byte[] packet, int packetLen) { int profile = 2; // AAC LC int freqIdx = 4; // 44.1KHz int chanCfg = 2; // CPE // fill in ADTS data packet[0] = (byte) 0xFF; packet[1] = (byte) 0xF9; packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2)); packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11)); packet[4] = (byte) ((packetLen & 0x7FF) >> 3); packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F); packet[6] = (byte) 0xFC; }