我们先来分析下为什么使用2进制来进行通讯中的数据交换:
一 优点:
1、节省数据流量消耗;一个byte有 8个bit能代表好多意思呢。
2、增加可靠性;数据被拦截,对方无文档也解不开这数据到底描述的是什么。
二 缺点:
1、开发阶段,出现bug 不好排除bug,没字符串来的直观.
2、数据粘包,串包,一个字节出错,全盘皆错。
但是这2个缺点在技术上是可避免的。下面介绍2个读取byte 写byte的2个工具类
ReadBuffer:
package io.xilnk.wifi.sdk.buffer;
import io.xilnk.wifi.sdk.util.XTUtils;
/**
* 读取Buff使用
*
* @author Liuxy
* @2015年1月14日上午11:51:09 </br>
* @explain
*/
public class ReadBuffer {
// 当前读取数据的索引
private int index;
// 数据
private byte[] buf;
public ReadBuffer(byte[] bys, int offset) {
buf = bys;
this.index = offset;
}
/**
* 设置偏移量.不推荐使用
*
* @deprecated
* @param index
*/
public void setIndex(int offset) {
this.index = offset;
}
/**
* 读取结束
*/
public void finsh() {
buf = null;
index = 0;
}
/**
* 返回所有的byte[]
*
* @return
*/
public byte[] array() {
return buf;
}
/**
* 每次读取,需要把当前索引值加起来
*
* @param count
*/
private void addIndex(int count) {
index += count;
if (buf.length == index) {
finsh();
}
}
<pre name="code" class="java"> /**
* 获取当前的偏移量
*
* @return
*/
public int getOffset() {return index; } /** * 读取一个字节布尔 * * @return */ public boolean readBoolean() {byte b = buf[index];addIndex(1);// 不等于0就是true,等于0为falsereturn b != 0; } @Override public String toString() {// TODO Auto-generated method stubreturn "当前索引: " + index + " 数据总长度 :" + buf.length + " " + buf; } /** * 读取一个byte * * @return */ public byte readByte() {byte b = buf[index];addIndex(1);return b; } /** * 读取剩下的byte[] * * @return */ public byte[] readEndByte() {byte[] bs = new byte[buf.length - index];System.arraycopy(buf, index, bs, 0, bs.length);index += bs.length;finsh();return bs; } /** * 读取4个字节的int * * @return */ public int readInt() {byte[] b = new byte[4];System.arraycopy(buf, index, b, 0, b.length);addIndex(b.length);return XTUtils.bytesToInt2(b); } /** * 读取2个字节的Short * * @return */ public short readShort() {short s = XTUtils.byte2Short(buf, index);addIndex(2);return s; } /** * 读取指定大小的byte[] * * @return */ public byte[] readBytes(int size) {byte[] bs = new byte[size];System.arraycopy(buf, index, bs, 0, bs.length);addIndex(size);return bs; }}
WriteBuffer:
package io.xilnk.wifi.sdk.buffer;
import io.xilnk.wifi.sdk.util.XTUtils;
/**
* 写数据
*
* @author Liuxy
* @2015年1月14日上午11:51:58 </br>
* @explain
*/
public class WriteBuffer {
// 当前的数据
private byte[] buf;
// 当前写入的索引
private int index;
/**
*
* @param size
* 需要写入多大数据
*/
public WriteBuffer(int size) {
buf = new byte[size];
index = 0;
}
/**
* 写2个字节short
*
* @param srt
*/
public void writeShort(short srt) {
byte[] srtbyte = XTUtils.shortToByteArray(srt);
writeBytes(srtbyte);
}
/**
* 写2个字节short
*
* @param srt
*/
public void writeShort(int srt) {
writeShort((short) srt);
}
/**
* 获取byte array
*
* @return
*/
public byte[] array() {
return buf;
}
/**
* 写4个字节int
*
* @param srt
*/
public void writeInt(int i) {
byte[] srtbyte = XTUtils.intToByteArray(i);
writeBytes(srtbyte);
}
/**
* 写入byte[]
*
* @param srt
*/
public void writeBytes(byte[] data) {
int len = data.length;
System.arraycopy(data, 0, buf, index, len);
index += len;
}
// public byte[] getBuf() {
//
// return buf;
// }
/**
* 返回当前写的索引值
*
* @return
*/
public int getIndex() {
return index;
}
/**
* 写入1个字节的布尔
*
* @param srt
*/
public void writeBoolean(boolean b) {
byte by = 0;
if (b) {
by = 1;
} else {
by = 0;
}
writeByte(by);
}
/**
* 写入1个字节的byte
*
* @param srt
*/
public void writeByte(int b) {
writeByte((byte) b);
}
public void writeByte(byte b) {
buf[index] = b;
index++;
}
// public static WriteBuffer newByteBuf(int size) {
// return new WriteBuffer(size);
// }
}
最后奉上 byte 转换从几大基本数据类型的常用工具:
/**
* byte[] 转int 高位在前,低位在后
*
* @param src
* @return
*/
public static int bytesToInt2(byte[] src) {
int value;
value = (int) (((src[0] & 0xFF) << 24) | ((src[0 + 1] & 0xFF) << 16)
| ((src[0 + 2] & 0xFF) << 8) | (src[0 + 3] & 0xFF));
return value;
}
/**
* 将16位的short转换成byte数组
*
* @param s
* short
* @return byte[] 长度为2
* */
public static byte[] shortToByteArray(short s) {
byte[] targets = new byte[2];
for (int i = 0; i < 2; i++) {
int offset = (targets.length - 1 - i) * 8;
targets[i] = (byte) ((s >>> offset) & 0xff);
}
return targets;
}
/**
* 将32位整数转换成长度为4的byte数组
*
* @param s
* int
* @return byte[]
* */
public static byte[] intToByteArray(int i) {
byte[] result = new byte[4];
result[0] = (byte) ((i >> 24) & 0xFF);
result[1] = (byte) ((i >> 16) & 0xFF);
result[2] = (byte) ((i >> 8) & 0xFF);
result[3] = (byte) (i & 0xFF);
return result;
}
/**
* 把byte转化成 二进制.
*
* @param aByte
* @return
*/
public static String getBinString(byte aByte) {
String out = "";
int i = 0;
for (i = 0; i < 8; i++) {
int v = (aByte << i) & 0x80;
v = (v >> 7) & 1;
out += v;
}
return out;
}
/**
* buf转 String
*
* @param buf
* @return
*/
public static String buf2String(byte[] buf) {
return new String(buf, Charset.forName(ENCODING));
}
/**
* String 转 buf
*
* @param buf
* @return
*/
public static byte[] string2buf(String text) {
return text.getBytes(Charset.forName(ENCODING));
}
/**
* 截取 byte
*
* @param src
* 源数据
* @param off
* 偏移量
* @param len
* 长度
* @return
*/
public static byte[] subBytes(byte[] bytes, int offset, int len) {
byte[] b = new byte[len - offset];
System.arraycopy(bytes, offset, b, 0, len);
return b;
}
/**
* 无符号的short
*
* @param s
* @return
*/
public static int UnsignedShort(int s) {
if (s < 0) {
s = 65536 + s;
}
return s;
}
使用方法 跟netty框架的 ByteBuf 差不多。