首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java實現CRC16循環冗餘校驗算法詳解

     編輯:Java 相關知識

算法原理與設計

CRC16(Cyclic Redundancy Check 16-bit)是數據通信中廣泛使用的錯誤檢測算法。本文提供完整的Java實現,包含二進制轉換、多項式除法運算及十六進制輸出功能。

CRC16算法流程圖

核心代碼實現

import java.io.IOException;

public class CRC16Checker {
    // CRC-16-CCITT 多項式: x^16 + x^12 + x^5 + 1 (0x1021)
    // 索引數組對應多項式非零項的位置: 16, 12, 5, 0
    private static int[] polynomial = new int[] { 16, 15, 2, 0 };

    /** 將字符串轉換為位元組陣列 (每字符8位) */
    private static int[] getBinary(String text) {
        StringBuffer num = new StringBuffer();
        for (int i = 0; i < text.length(); i++) {
            String s = Integer.toBinaryString(text.charAt(i));
            // 補齊至8位
            for (int j = 8 - s.length(); j > 0; j--) num.append('0');
            num.append(s);
        }
        int[] code = new int[num.length()];
        for (int i = 0; i < code.length; i++) {
            code[i] = Character.getNumericValue(num.charAt(i));
        }
        return code;
    }

    /** 位元組陣列轉十六進制字符串 */
    private static String toHex(int[] num) {
        StringBuffer hex = new StringBuffer(num.length / 4);
        char[] ch = new char[4];
        for (int i = 0; i < num.length; ) {
            ch[0] = Character.forDigit(num[i++], 2);
            ch[1] = Character.forDigit(num[i++], 2);
            ch[2] = Character.forDigit(num[i++], 2);
            ch[3] = Character.forDigit(num[i++], 2);
            hex.append(Integer.toHexString(Integer.parseInt(String.valueOf(ch), 2)));
        }
        return hex.toString();
    }

    /** CRC核心計算:模二多項式除法 */
    public static int[] makeCRCCodes(int[] sourceCodes, int[] polynomial) {
        int sourceLength = sourceCodes.length;
        int crcLength = polynomial[0]; // 校驗位長度 = 多項式最高次
        int[] crcCodes = new int[sourceLength + crcLength];
        
        // 複製原始數據
        System.arraycopy(sourceCodes, 0, crcCodes, 0, sourceLength);
        
        // 模二除法運算
        for (int i = 0; i < sourceLength; i++) {
            // 輸入位與第一寄存器異或
            int feedback = (crcCodes[sourceLength] + sourceCodes[i]) % 2;
            
            // 寄存器左移
            System.arraycopy(crcCodes, sourceLength + 1, crcCodes, sourceLength, crcLength - 1);
            
            // 反饋位進入最後寄存器
            crcCodes[crcCodes.length - 1] = feedback;
            
            // 根據多項式更新中間寄存器
            for (int j = polynomial.length - 2; j > 0; j--) {
                int pos = crcCodes.length - polynomial[j] - 1;
                crcCodes[pos] = (crcCodes[pos] + feedback) % 2;
            }
        }
        return crcCodes;
    }

    public static void main(String[] args) throws IOException {
        System.out.print("輸入十六進制數據: ");
        StringBuffer buf = new StringBuffer();
        int ch = System.in.read();
        while (ch != '\r' && ch != '\n') {
            buf.append((char)ch);
            ch = System.in.read();
        }
        
        int[] binary = getBinary(buf.toString());
        binary = makeCRCCodes(binary, polynomial);
        
        // 輸出二進制 (每4位分組)
        for (int i = 0; i < binary.length; ) {
            for (int j = 0; j < 4 && i < binary.length; j++, i++) {
                System.out.print(binary[i]);
            }
            System.out.print(' ');
        }
        System.out.println("\nCRC16校驗碼: " + toHex(binary));
    }
}

測試驗證結果

輸入數據ASCII碼完整結果CRC16校驗碼
A414101860168 (0000 0001 1000 0110)
CRC16TEST43 52 43 31 36 54 45 53 54435243313654455354fb66fb66 (1111 1011 0110 0110)
5k35 6b356b3f793f79 (0011 1111 0111 1001)

關鍵技術點解析

  • 多項式表示:使用索引數組{16, 15, 2, 0}表示x^16 + x^15 + x^2 + 1,而非標準CCITT多項式,屬於變體實現
  • 模二運算:所有加減法均為異或操作,無進位借位
  • 移位寄存器模擬:通過數組複製實現硬件移位寄存器邏輯
  • 大端序處理:高位在前,符合網絡傳輸標準

應用場景

適用於Modbus協議、串口通信、文件完整性校驗等場景。可通過修改polynomial數組適配不同CRC標準(如CRC-16-IBM: {16, 15, 2, 0},CRC-16-CCITT: {16, 12, 5, 0})。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved