版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013564742/article/details/82117630
简介
最近由于需要对接校园的刷卡机支付,协议需要用到异或校验。参照校验的流程对相邻数组进行异或,得出的结果却与示例的不一样,而且还是负数。
起先以为自己的算法或者数据有问题,但是检查了一遍后还是一样。
分析原因
由于协议中有字段表示的数值大于127,如协议中该字段16进制为0XA2,本来数值应该是162,结果转变成byte时变成了-94,异或校验后该字段的数值变为了负数,导致异或校验的结果不正确,这是因为java中的byte是有符号位的byte,这点和c++不一样,因此可表示的数据为-127~127(最高位为符号位)。知道了原因,剩下的就是问题的解决了。
解决方法
既然是数值太大导致byte溢出了,那么只要解决溢出的问题就好了。在这里我们只关心校验的结果,因此把byte用int类型来表示就能解决数值的问题了。
可以将异或的结果使用int类型表示(这是为了防止结果出现负数),在异或的过程中,将溢出的byte数据(即数值超出127的)通过&0xff将符号为变成正数,同时由于byte保存不了变为正数的数据,需要分配一个临时变量来保存并参与运算。
以下为解决的代码:
/** 获取指令异或值
* @param datas
* @return
*/
private int getXOR(byte[] datas) {
int temp = datas[1]; // 此处首位取1是因为本协议中第一个数据不参数异或校验,转为int防止结果出现溢出变成负数
for (int i = 2; i < datas.length; i++) {
int preTemp = temp;
int iData;
if (datas[i] < 0) {
iData = datas[i] & 0xff; // 变为正数计算
} else {
iData = datas[i];
}
if (temp < 0) {
temp = temp & 0xff; // 变为正数
}
temp ^= iData;
System.out.println(preTemp + "异或" + iData + "=" + temp);
}
return temp;
}