Java字节数组处理工具类-Mina的IoBuffer封装
处理网络数据的项目中经常需要处理字节数据,Java的ByteBuffer很强大,但是Mina和Netty两个常用的网络通信框架都拥有自己的数据读取Buffer,分别是IoBuffer和ByteBuff,IoBuffer基于Java原生ByteBuffer封装而成,ByteBuff则是Netty自己独有的字节数据Buffer,可以实现零拷贝。
封装
由于项目中经常需要按int、short、byte[]、String数据类型读写数据协议,需要一个合适的数据处理buffer做协议的decode和encode,已经有IoBuffer和ByteBuff这样强大的轮子,无需再造。所以选择其中一种应用到项目中,ByteBuff功能强大,但是和Netty框架结合较深,如果用不到其中的通信功能,不妨直接使用Mina中的IoBuffer中的代码直接封装一个针对性强的数据处理Buffer。
例如:下面是一个针对IoBuffer的简单封装。
public class JBuffer {
private IoBuffer buff;
public JBuffer() {
this.buff = IoBuffer.allocate(2048);
}
public JBuffer(int size) {
this.buff = IoBuffer.allocate(size);
}
public JBuffer(IoBuffer buff) {
this.buff = buff;
}
public JBuffer(byte[] bytes) {
this.buff = IoBuffer.wrap(bytes);
}
public JBuffer mark() {
this.buff.mark();
return this;
}
public int markValue() {
return this.buff.markValue();
}
public JBuffer reset() {
this.buff.reset();
return this;
}
public JBuffer flip() {
this.buff.flip();
return this;
}
public int remaining() {
return this.buff.remaining();
}
public boolean hasRemain() {
return this.buff.remaining() > 0;
}
public int position() {
return this.buff.position();
}
public void position(int newPosition) {
this.buff.position(newPosition);
}
public void clear() {
this.buff.clear();
}
public void putByte(byte a) {
this.buff.put(a);
}
public void putShort(short a) {
this.buff.putShort(a);
}
public void putBytes(byte[] a) {
this.buff.put(a);
}
public void putInt(int a) {
this.buff.putInt(a);
}
public void putString(String str) {
try {
this.buff.putString(str, Charset.forName("GBK").newEncoder());
} catch (CharacterCodingException e1) {
e1.printStackTrace();
}
}
public void putString(String str, int len) {
try {
this.buff.putString(str, len, Charset.forName("GBK").newEncoder());
} catch (CharacterCodingException e1) {
e1.printStackTrace();
}
}
public byte get(int index) {
return this.buff.get(index);
}
public byte getByte() {
return this.buff.get();
}
public byte[] getBytes(int len) {
byte[] data = new byte[len];
this.buff.get(data);
return data;
}
public byte[] getBytes() {
byte[] data = new byte[this.buff.limit() - this.buff.position()];
this.buff.get(data);
return data;
}
public int getInt() {
return this.buff.getInt();
}
public short getShort() {
return this.buff.getShort();
}
public String getString() {
try {
String str = this.buff.getString(Charset.forName("GBK").newDecoder());
return str;
} catch (CharacterCodingException e) {
e.printStackTrace();
return "";
}
}
public String getString(int len) {
try {
String str = this.buff.getString(len, Charset.forName("GBK").newDecoder());
return str;
} catch (CharacterCodingException e) {
e.printStackTrace();
return "";
}
}
public byte[] array() {
int pos = this.buff.position();
byte[] data = new byte[pos];
this.buff.position(0);
this.buff.get(data);
return data;
}
}
上面的代码主要用于从数据buffer中读取和输入不同类型的数据,包括byte、bytes、short、int、String。
应用
简单写个用例测试一下:
@Test public void testBuffer() {
String str = "1234";
JBuffer buffer = new JBuffer();
buffer.putString(str, 10); // 31 32 33 34 00 00 00 00 00 00 (10个字节)
buffer.putShort((short) 100); // 00 64 (2个字节)
System.out.println("数据长度:" + buffer.position());
buffer.flip();
System.out.println("获取字符串:" + buffer.getString() + " position:" + buffer.position());//取走31 32 33 34 00(共5个字节)其中00为结束符'\0'
System.out.println("取走为0数据:" + buffer.getBytes(5).length + " position:" + buffer.position());//取走00 00 00 00 00(5个字节)
System.out.println("获取short:" + buffer.getShort() + " position:" + buffer.position());//取走 00 64(2个字节)
}
输出:
数据长度:12
获取字符串:1234 position:5
取走为0数据:5 position:10
获取short:100 position:12
非常简单的数据读取操作,short和int等比较好理解,输入字符串String的时候如果在putString(str, len)
加第二个参数len,表示如果字符串字节数小于len会在buffer里填充0x00,而getString()
会读到有’\0’的位置,若没有’\0’则会读到数据结尾。
OK,有其它好的工具欢迎留言分享~