天天看点

JAVA 实现crc8(多项式X8+x5+x4+1),byte的各种问题

遇到的坑

一、符号右移及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

JAVA 实现crc8(多项式X8+x5+x4+1),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;
    }