最近客户有CRC校验的需求,即但愿Android端对字符串进行校验,并将生成的2个字节的CRC校验码追加到字符串中,而后一块儿写入文件。当系统联网后,会经过写入的字符串去向服务器请求设备序列号,服务器会根据该字符串的原始字符串(不含校验码)进行校验,若是校验出来的值跟最后两个字节的校验码匹配上,则下发一个序列号,不然为空。数组
CRC的校验方式多种多样,每一个客户都有本身的校验方式。这次客户提供了C语言版本的校验方式,这边要将C语言版本的校验转化为Java版本。安全
但因为C语言和Java的基本类型对不上,如C语言的变量类型有符号之分,而Java则统一都带符号,并无所谓的无符号类型变量。若未接触过的同窗可能要费点时间去作转化,这里给出转化的技巧。服务器
这里先上C语言版本的校验,代码以下:微信
unsigned short int CRC_TABLE[16]={0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7,
0x8108,0x9129,0xA14A,0xB16B,0xC18C,0xD1AD,0xE1CE,0xF1EF};
unsigned int getCRC( char *pbuffer, unsigned int buff_len)
{
unsigned short int mCRC;
unsigned char mTemp;
mCRC=0x0;
while(buff_len--)
{
mTemp=(unsigned char)(mCRC>>0x0C);
mCRC<<=4;
mCRC^=CRC_TABLE[mTemp^((*pbuffer)>>0x04)];
mTemp=(unsigned char)(mCRC>>0x0C);
mCRC<<=4;
mCRC^=CRC_TABLE[mTemp^((*pbuffer)&0x0F)];
pbuffer++;
}
return (unsigned int)mCRC;
}
复制代码
通常CRC校验都会有一个码表,用于生成校验码。post
因为C语言有有符号和无符号之分,而Java则没有这种区分,那么在转化的时候,要注意符号的问题。这里有个技巧,转化时,C语言和Java的类型对应关系以下:动画
int->int
short->int
char*->String/byte[]
char->short
复制代码
什么意思?即C语言使用int类型的变量时,Java也使用int类型变量,C语言使用short类型变量时,Java使用int类型变量。。。spa
贴上Java的CRC校验代码,你们对照着看就明白:3d
private byte[] getCRC16(String data) {
int crc = 0x0; //这里只需用到int的低16位便可
short tem = 0x00;
char[] ch = data.toCharArray();
for (char c : ch) {
byte b = (byte)c;
tem = (short)((crc >> 0x0c) & 0x00ff);
crc <<= 4;
crc &= 0x0000ffff; //保证高16位一直为0
crc ^=crc16tab[(tem ^ (b >> 0x04))&0x000000ff]; //获取高八位CRC校验码
crc &= 0x0000ffff;
tem = (short)((crc >> 0x0c) & 0x00ff);
crc <<= 4;
crc &= 0x0000ffff;
crc ^= crc16tab[(tem ^ (b & 0x0f)) & 0x000000ff]; //获取低八位CRC校验码
crc &= 0x0000ffff;//只需低16位的CRC校验码
}
byte[] res = intToByteArray(crc);//将int类型转为byte数组
return res;
}
复制代码
须要注意的是,在CRC校验中,有针对16进制字节进行校验的,有针对字符进行校验的,好比须要校验以下内容:code
0001020304050607
复制代码
那么这时须要确认清楚,究竟是校验字节,仍是逐个字符的进行校验。本文则是逐个字符进行校验。cdn
CRC校验多见于通信协议中,会对通信内容进行校验,而后将生成的校验码追加到通信帧中。也有像本文这样子的,对某个文件中的内容进行校验,而后生成校验码,提升安全性。
若是文章存在错误描述,可直接留言,一块儿探讨!
我在微信公众号也有写文章,更新比较及时,有兴趣者能够扫描以下二维码,或者微信搜索【Android系统实战开发】,关注有惊喜哦!