首先先说一下数据包的格式,它由以下内容组成:
Header:数据包头"AA"
Data length:用于声明Data segment的长度
Data segment:包含实际意义字符串的16进制转码
CRC:相应用于数据验证的字符码
Tail:数据包尾"BB"
在表达形式上,1Byte=2字符,所以包头AA包尾BB的大小都是2字符,因此Data length(数据段长)也是两字符(即01~99),而作为Data segment的16进制转码,一个字符转16进制后对应2字符(例如:1=>31和A=>41)。
下面开始主要内容:
首先,创建一个Project,命名为Packet,当然,也可以根据喜好来命名:
然后再创建好的项目的src文件夹上,右键新建一个Package,命名PartA:
然后在这个Package上继续邮件新的类CRC16,最终如图:
建好之后开始看第一个方法getCRC(已给出),代码如下:
public static String getCRC(byte[] bytes) {
int CRC = 0x0000FFFF;
int POLYNOMIAL = 0x0000A001;
int i, j;
for (i = 0; i < bytes.length; i++) {
CRC =CRC^ ((int) bytes[i] & 0x000000ff);
for (j = 0; j < 8; j++) {
if ((CRC & 0x00000001) != 0) {
CRC >>= 1;
CRC =CRC^POLYNOMIAL;
} else {
CRC = CRC>>1;
}
}
}
String result = Integer.toHexString(CRC).toUpperCase();
if (result.length() !=4 ) {
StringBuffer sb = new StringBuffer("0000");
result = sb.replace(4-result.length(),4,result).toString();
}
return result.substring(2,4)+result.substring(0,2);
}
这个方法接受一个数组类型的变量(byte[]),并且返回一个字符串,字符串就是由该数组转化而来的CRC码,固定只有 2bytes(即4字符)。
那想要实现 数据 与 数据包 的转化,还缺以下方法:
1.字符串转16进制。
2.16进制转数组byte[]。
3.16进制转字符串。
在下面分别实现:
1-字符串转16进制:
public static String strToHex(String original_data) {
String Hexstr = "";
for (int i = 0; i < original_data.length(); i++)
Hexstr += Integer.toHexString(original_data.charAt(i));
return Hexstr;
}
该方法接受一个常规字符串,返回一个16进制字符串。
2-16进制转数组byte[]:
public static byte[] hexToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] bytes = new byte[length];
String hexDigits = "0123456789abcdef";
for (int i = 0; i < length; i++) {
int h = hexDigits.indexOf(hexChars[i*2]) << 4;
int l = hexDigits.indexOf(hexChars[i*2 + 1]);
if(h == -1 || l == -1) return null;
bytes[i] = (byte) (h | l);
}
return bytes;
}
该方法接受一个16进制字符串,返回一个byte[]。
3-16进制转字符串:
public static String hexToStr(String s) {
if (s == null || s.equals("")) {
return null;
}
s = s.replace(" ", "");
byte[] baKeyword = new byte[s.length() / 2];
for (int i = 0; i < baKeyword.length; i++) {
try {
baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
} catch (Exception e) {
e.printStackTrace();
}
}
try {
s = new String(baKeyword, "UTF-8");
new String();
} catch (Exception e1) {
e1.printStackTrace();
}
return s;
}
该方法接受一个16进制字符串,返回一个转换后的常规字符串。
有了这三个主要方法,就可以开始调用并生成数据包(DataPacket)了。
此时,一个字符串“ABC”转CRC码的实际情况如下:
strToHex("ABC"):将ABC转为16进制
=>hexToBytes(strToHex(s)):将转换后的16进制字符串再转换成byte[]
=>getCRC(hexToBytes(strToHex(s))):将转换好的byte[]传递给getCRC,最终得到CRC码。
代码如下:
public static String getCRC_code(String s) {
String crc = getCRC(hexToBytes(strToHex(s)));
return crc;
}
在该类中再定义一个主方法进行测试,结果如下:
public static void main(String[] args) {
System.out.println(getCRC_code("123A"));
System.out.println(hexToStr("31323341"));
System.out.println(strToHex("123A"));
System.out.println(hexToStr(strToHex("123A")));
}
//运行结果
//7BD7
//123A
//31323341
//123A
到这里时,CRC类就构建完成了