动态buffer,通过头部指针以及有效长度来定义buffer的有效数据区,可循环使用整个buffer区域。支持自动增加buffer大小,从buffer中读取数据,往buffer写数据。修改buffer指定位置指定长度的数据。
1、动态增加buffer大小。
重新分配一个byte数组,长度满足当前需求,将之前byte数组的内容copy至新byte数组。重置buffer的头部指针,大小,有效长度等值。
/**
* realloc buffer ,new size equals with old size plus len
* @param len
*/
public void reAlloc(int len){
byte[] tmp=new byte[size+len];
if(validLen>0){
byte[] tmp1=read(validLen);
for(int i=0;i<tmp1.length;i++){
tmp[i]=tmp1[i];
}
this.validLen=tmp1.length;
}
this.buf=tmp;
this.head=0;
this.size+=len;
}
2、从buffer指定位置读取指定长度数据
/**
* read data ,not move the head nor the validLen
* @param len
* @return
*/
public byte[] read(int offset,int len){
if(len<=0 || validLen<=0){
return null;
}
if(len>validLen){
return null;
}
byte[] readBuf=new byte[len];
if(head+offset+len<=size){
for(int i=0;i<len;i++){
readBuf[i]=buf[head+offset+i];
}
}else if(head+offset+len>size){
//first read from head to size,total read bytes is size-head
for(int i=0;i<size-head-offset;i++){
readBuf[i]=buf[head+offset+i];
}
//then read from the beginning of the buffer,read bytes is len+head-size
for(int i=0;i<len+head+offset-size;i++){
readBuf[size-head-offset+i]=buf[i];
}
}
return readBuf;
}
3、往buffer写数据
/**
* append data to buffer,increase validLen
* @param src
* @param len
*/
public void append(byte[] src,int len){
if(getAvailabeSize()<len){
reAlloc(len);
}
if(head+validLen+len<=size){
for(int i=0;i<len;i++){
buf[head+validLen+i]=src[i];
}
}else if(head+validLen+len>size){
if(head+validLen>=size){
for(int i=0;i<len;i++){
buf[head+validLen-size+i]=src[i];
}
}else if(head+validLen<size){
//first append from head+validLen to size
for(int i=0;i<size-head-validLen;i++){
buf[head+validLen+i]=src[i];
}
//then append from the beginning of the buffer
for(int i=0;i<len+head+validLen-size;i++){
buf[i]=src[size-head-validLen+i];
}
}
}
validLen+=len;
}
4、修改buffer的数据内容
public void modify(int offset,int len,byte[] src){
for(int i=0;i<len;i++){
buf[offset+i]=src[i];
}
}
5、完整代码片
package com.klaus.utils;
public class Buffer {
private int size;
private byte[] buf=null;
public int validLen=0;
public int head=0;
public boolean isCompleted = false;
public Buffer(int size){
this.size=size;
this.buf=new byte[size];
this.head=this.validLen=0;
}
public Buffer(byte[] buf,int len){
this.buf=new byte[len];
for(int i=0;i<len;i++){
this.buf[i]=buf[i];
}
this.validLen=len;
this.head=0;
this.size=len;
}
public void init(){
head=0;
validLen=0;
isCompleted = false;
}
/**
* read data ,not move the head nor the validLen
* @param len
* @return
*/
public byte[] read(int len){
if(len<=0 || validLen<=0){
return null;
}
if(len>validLen){
return null;
}
byte[] readBuf=new byte[len];
if(head+len<=size){
for(int i=0;i<len;i++){
readBuf[i]=buf[head+i];
}
}else if(head+len>size){
//first read from head to size,total read bytes is size-head
for(int i=0;i<size-head;i++){
readBuf[i]=buf[head+i];
}
//then read from the beginning of the buffer,read bytes is len+head-size
for(int i=0;i<len+head-size;i++){
readBuf[size-head+i]=buf[i];
}
}
return readBuf;
}
/**
* read data ,not move the head nor the validLen
* @param len
* @return
*/
public byte[] read(int offset,int len){
if(len<=0 || validLen<=0){
return null;
}
if(len>validLen){
return null;
}
byte[] readBuf=new byte[len];
if(head+offset+len<=size){
for(int i=0;i<len;i++){
readBuf[i]=buf[head+offset+i];
}
}else if(head+offset+len>size){
//first read from head to size,total read bytes is size-head
for(int i=0;i<size-head-offset;i++){
readBuf[i]=buf[head+offset+i];
}
//then read from the beginning of the buffer,read bytes is len+head-size
for(int i=0;i<len+head+offset-size;i++){
readBuf[size-head-offset+i]=buf[i];
}
}
return readBuf;
}
/**
* read data ,and move the head ,decrease the validLen
* @param len
* @return
*/
public byte[] readAndMove(int len){
byte[] read = read(len);
//move head to new location,decrease validLen
validLen-=len;
if(head+len<=size){
head+=len;
if(head==size){
head=0;
}
}else{
head=(len+head-size);
}
return read;
}
/**
* append data to buffer,increase validLen
* @param src
* @param len
*/
public void append(byte[] src,int len){
if(getAvailabeSize()<len){
reAlloc(len);
}
if(head+validLen+len<=size){
for(int i=0;i<len;i++){
buf[head+validLen+i]=src[i];
}
}else if(head+validLen+len>size){
if(head+validLen>=size){
for(int i=0;i<len;i++){
buf[head+validLen-size+i]=src[i];
}
}else if(head+validLen<size){
//first append from head+validLen to size
for(int i=0;i<size-head-validLen;i++){
buf[head+validLen+i]=src[i];
}
//then append from the beginning of the buffer
for(int i=0;i<len+head+validLen-size;i++){
buf[i]=src[size-head-validLen+i];
}
}
}
validLen+=len;
}
/**
* realloc buffer ,new size equals with old size plus len
* @param len
*/
public void reAlloc(int len){
byte[] tmp=new byte[size+len];
if(validLen>0){
byte[] tmp1=read(validLen);
for(int i=0;i<tmp1.length;i++){
tmp[i]=tmp1[i];
}
this.validLen=tmp1.length;
}
this.buf=tmp;
this.head=0;
this.size+=len;
}
public void modify(int offset,int len,byte[] src){
for(int i=0;i<len;i++){
buf[offset+i]=src[i];
}
}
/**
* get available buffer size,if not enough ,call reAlloc to add the buffer size dymaticly
* @return
*/
public int getAvailabeSize(){
return size-validLen;
}
public byte[] getBuffer(){
return buf;
}
public int getSize(){
return size;
}
}