概述
本人android码农一个,这几天需要对接一个服务器,使用的是GTP协议,看了一下协议,顿时觉得蒙逼了。因为存储数据节约到了bit位,作为用惯了JAVA的人,顿时觉得这是得有多抠啊,不过由于我跟服务器用的是长连接,数据交互很频繁,所以这样其实大大节省了数据量,对于使用GPRS流量的用户是很有必要的。
对接中我遇到的第一个问题就是数据封装和解析都是按bit位算的,一个数据占多少个bit这样的。现在遇到的问题就比如说,现在用两个byte来存CTRL,三个bit用来存版本号,一个bit用来做判断是否需要ACK,三个bit用来存优先级,9个bit用来存报文序号。对于C语言来说,这没什么,定义一个联合体就行了,但是对于java来说,就有点晕了,因为平常我们用到的最小的是byte,要这样操作bit位的话,我们需要一大堆位运算,想想就很可怕。虽然可以用C写,然后用JNI调用,但是不甘心我的还是想用java来更简单得实现。终于在洗澡的时候让我想到了,用string来实现。
先说说原理,就是把一个string对象当成一块内存,里面存着一串bit,然后对里面的bit进行操作,最后再把这堆bit封装成byte。
现在就以 用两个byte来存CTRL,三个bit用来存版本号,一个bit用来做判断是否需要ACK,三个bit用来存优先级,9个bit用来存报文序号 这个需求来实现吧。
1、先封装三个方法一个是把int转成String格式的bit串,一个是string格式的bit串转为byte,一个是设定好bit串长度 。
/**
* 将byte转成string格式bit串并省略前面的0
*/
public static String byteToBitFS(byte b) {
boolean hn = false;
byte[] bits = new byte[8];
bits[0] = (byte)((b >> 7) & 0x1);
bits[1] = (byte)((b >> 6) & 0x1);
bits[2] = (byte)((b >> 5) & 0x1);
bits[3] = (byte)((b >> 4) & 0x1);
bits[4] = (byte)((b >> 3) & 0x1);
bits[5] = (byte)((b >> 2) & 0x1);
bits[6] = (byte)((b >> 1) & 0x1);
bits[7] = (byte)((b >> 0) & 0x1);
StringBuffer sb = new StringBuffer();
for(byte temp : bits){
if(hn){
sb.append(temp);
}else{
if(temp != 0x00){
sb.append(temp);
hn=true;
}
}
}
return sb.toString();
}
/**
* 将string格式的bit串转成byte
*/
public static byte BitToByte(String byteStr) {
int re, len;
if (null == byteStr) {
return 0;
}
len = byteStr.length();
if (len != 4 && len != 8) {
return 0;
}
if (len == 8) {
if (byteStr.charAt(0) == '0') {
re = Integer.parseInt(byteStr, 2);
} else {
re = Integer.parseInt(byteStr, 2) - 256;
}
} else {
re = Integer.parseInt(byteStr, 2);
}
return (byte) re;
}
/**
* 检查bit是长度是否足够,不够前面添0,超出返回null
*/
public static String resetBitStrand(String str, int length) {
if (str.length() > length) {
return null;
}
StringBuffer sb = new StringBuffer();
if (str.length() < length) {
for (int i = 0; i < length - str.length(); i++) {
sb.append("0");
}
}
sb.append(str);
return sb.toString();
}
* 检查bit是长度是否足够,不够前面添0,超出返回null
*/
public static String resetBitStrand(String str, int length) {
if (str.length() > length) {
return null;
}
StringBuffer sb = new StringBuffer();
if (str.length() < length) {
for (int i = 0; i < length - str.length(); i++) {
sb.append("0");
}
}
sb.append(str);
return sb.toString();
}
2、先把2个byte也就是16个bit的位置准备好,开始添加数据
public static void setCTRL(byte version, boolean needack, byte priority,
int sno) {
StringBuffer sb = new StringBuffer();
// 添加版本号
String ver = resetBitStrand(byteToBitFS(version), 3);
sb.append(ver);
// 添加是否需要ack
sb.append(needack ? 1 : 0);
// 添加优先级
String str_priority = resetBitStrand(byteToBitFS(priority), 3);
sb.append(str_priority);
// 添加包序号
String str_sno = resetBitStrand(Integer.toBinaryString(sno), 9);
sb.append(str_sno);
//最后封装完成的bit串
String bitStand = sb.toString();
//将bit串转为byte
byte b1 = BitToByte(bitStand.substring(0,8));
byte b2 = BitToByte(bitStand.substring(8,16));
System.out.println("最后的结果bit串: "+bitStand+"
两个byte:"+b1+"-"+b2);
}
到这里就封装就大功告成啦,解析反其道而行就行啦,我就不再多说了。
这种实现方法不是唯一的,也不是最好的,但是也提供了一个例子.
最后
以上就是清秀秋天为你收集整理的JAVA实现类似C语言联合体般 充分使用bit位存储数据的方法之一的全部内容,希望文章能够帮你解决JAVA实现类似C语言联合体般 充分使用bit位存储数据的方法之一所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复