遇到的坑
一、符号右移及C#java的区别
1、定协议的时候,后台的是用C#写的,在协议中给了一个crc封装的函数
public static byte CRC8(byte[] buffer)
{
byte crc = ;
for (int j = ; j < buffer.Length; j++)
{
crc ^= buffer[j];
for (int i = ; i < ; i++)
{
if ((crc & ) != )
{
crc >>= ;
crc ^= ;
}
else
{
crc >>= ;
}
}
}
return crc;
}
在封装自己的方法时,我直接把这个方法封装静态类里面使用,结果开发硬件的人员反应:跟他算出来的crc不一致,其他解密后的数据一致。然后讨论了一下,问题定位在“字节移动“上。
1.C# 的byte
2.Java的byte是有符号的,而且重点内容对byte 的 + - * / >> >>> << & | ^ (加,减,乘,除,右移,左移,无符号右移,位与,位或,位异或)操作,均会是首先将byte转化为int, 再行运算。
/**
解决的方法,首先解决符号移动的问题,直接用无符号右移即可 ">>>"
因为byte会转成int来运算,所以在右移的时候要注意最高会变成1,所以可以与0xff,使得低位外的字节置0;
0000 0000 0000 0000 0000 0000 xxxx xxxx
**/
public static int calcCrc8(byte[] data){
byte crc = ;
for (int j = ; j < data.length; j++)
{
crc ^= data[j];
for (int i = ; i < ; i++)
{
if ((crc & ) != )
{
crc = (byte) (((crc & ))>>> );
crc ^= ;
}
else
{
crc = (byte) (((crc & ))>>> );
}
}
}
return crc;
}
当然,我也找了第二种更快的方法计算crc;查表法 (适合crc的多项式X8+X5+X4+1)
static byte[] crc8_tab = { (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) ,
(byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) ,
(byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) ,
(byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , (byte) , };
/**
* 计算数组的CRC8校验值
*
* @param data
* 需要计算的数组
* @return CRC8校验值
*/
public static byte calcCrc(byte[] data) {
return calcCrc8(data, , data.length, (byte) );
}
/**
* 计算CRC8校验值
*
* @param data
* 数据
* @param offset
* 起始位置
* @param len
* 长度
* @return 校验值
*/
public static byte calcCrc8(byte[] data, int offset, int len) {
return calcCrc8(data, offset, len, (byte) );
}
/**
* 计算CRC8校验值
*
* @param data
* 数据
* @param offset
* 起始位置
* @param len
* 长度
* @param preval
* 之前的校验值
* @return 校验值
*/
public static byte calcCrc8(byte[] data, int offset, int len, byte preval) {
byte ret = preval;
for (int i = offset; i < (offset + len); ++i) {
ret = crc8_tab[( & (ret ^ data[i]))];
}
return ret;
}