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

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校驗碼 |
|---|---|---|---|
| A | 41 | 410186 | 0168 (0000 0001 1000 0110) |
| CRC16TEST | 43 52 43 31 36 54 45 53 54 | 435243313654455354fb66 | fb66 (1111 1011 0110 0110) |
| 5k | 35 6b | 356b3f79 | 3f79 (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})。