java byte数组异或校验时出现负数问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
    }

猜你喜欢

转载自blog.csdn.net/u013564742/article/details/82117630