基于Java实现的YmodemCRC校验工具

循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误,它是利用除法及余数的原理来作错误侦测的。本文是基于Java语言来实现对Ymodem数据的CRC校验的一种实现,可移植性强,主要针对公司嵌入式软件(或系统)传输到上位机的字节数组进行校验和上位机根据指定的数据生成CRC。

1、CCITT CRC-16循环冗余错误校验计算方法

CCITT CRC-16 (循环冗余错误校验)生成CRC-16校验字节的步聚如下:

2、代码实现

public class YmodemCRC {

    private byte[] mCRC = new byte[2];
    private byte[] source;

    public YmodemCRC(byte[] source) {
        this.source = source;
        int crc = 0x00;
        int polynomial = 0x1021;
        for (int index = 0; index < source.length; index++) {
            byte b = source[index];
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7 - i) & 1) == 1);
                boolean c15 = ((crc >> 15 & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit) crc ^= polynomial;
            }
        }
        crc &= 0xffff;
        mCRC = inttoByteArray(crc, 2);
    }

    /**
     * 整型转字节数组
     */
    private byte[] inttoByteArray(int iSource, int iArrayLen) {
        byte[] bLocalArr = new byte[iArrayLen];
        for (int i = 0; (i < 4) && (i < iArrayLen); i++) {
            bLocalArr[iArrayLen-1-i] = (byte) (iSource >> 8 * i & 0xFF);
        }
        return bLocalArr;
    }

    /**
     * 只获取CRC校验结果
     */
    public byte[] getCRC() {
        return mCRC;
    }

    /**
     * 获取带CRC检验的元数据
     */
    public byte[] getSourceWithCRC() {
        byte[] sourceWithCRC = new byte[source.length + mCRC.length];
        System.arraycopy(source, 0, sourceWithCRC, 0, source.length);
        System.arraycopy(mCRC, 0, sourceWithCRC, source.length, mCRC.length);
        return sourceWithCRC;
    }

    /**
     * 输入带CRC的元数据,校验CRC是否正确
     *
     * 如果正确则返回true,反之返回false
     */
    public static boolean checkCRC(byte[] sourceWithCRC) {
        if (sourceWithCRC.length <= 2) {
            return false;
        }
        byte[] source = new byte[sourceWithCRC.length - 2];
        byte[] crcBytes = new byte[2];
        System.arraycopy(sourceWithCRC, source.length, crcBytes, 0, 2);
        System.arraycopy(sourceWithCRC, 0, source, 0, source.length);
        YmodemCRC crc = new YmodemCRC(source);
        return crc.getCRC()[0] == crcBytes[0] && crc.getCRC()[1] == crcBytes[1];
    }
}

3、使用方式

该工具使用简单,现在针对常用的场景进行介绍。

    YmodemCRC.checkCRC(sourceWithCRC) 
    YmodemCRC crc = new YmodemCRC(source);
    //获取带CRC校验结果的数据
    crc.getSourceWithCRC();
    //只获取 CRC校验结果
    crc.getCRC();

标签:Java, Ymodem CRC, 循环冗余校验