GO、C#、Java实现同等CRC16算法校验
很多时候我们在做软件功能的时候不只使用一种程序设计语言,往往都是多种开发语言结合实现特定的需求。我讲述一下我在实现HJ212通信协议算法时用到的CRC16校验算法。
Go语言实现CRC16算法
func Crc16(strData string) (string, error) {
if strData == "" {
return "", fmt.Errorf("输入字符串不能为空")
}
var crc16Lo, crc16Hi byte
var saveLo, saveHi byte
bits := []byte(strData)
crc16Hi = 0xFF
crc16Lo = 0x00
for _, b := range bits {
crc16Lo = crc16Hi
crc16Hi = 0
crc16Lo ^= b
for g := 0; g < 8; g++ {
saveHi = crc16Hi
saveLo = crc16Lo
crc16Hi >>= 1
crc16Lo >>= 1
if saveHi%2 == 1 {
crc16Lo |= 0x80
}
if saveLo%2 == 1 {
crc16Hi ^= 0xA0
crc16Lo ^= 0x01
}
}
}
return fmt.Sprintf("%02X%02X", crc16Hi, crc16Lo), nil
}
C#实现CRC16算法
public static string Crc16(string strData)
{
byte crc16Lo, crc16Hi;
byte saveLo, saveHi;
byte[] bits = Encoding.ASCII.GetBytes(strData);
crc16Hi = 0xFF;
crc16Lo = 0x00;
for (int i = 0; i < bits.Length; i++)
{
crc16Lo = crc16Hi;
crc16Hi = 0;
crc16Lo ^= bits[i];
for (int g = 0; g < 8; g++)
{
saveHi = crc16Hi;
saveLo = crc16Lo;
crc16Hi /= 2;
crc16Lo /= 2;
if (saveHi % 2 == 1)
{
crc16Lo |= 0x80;
}
if (saveLo % 2 == 1)
{
crc16Hi ^= 0xA0;
crc16Lo ^= 0x01;
}
}
}
return crc16Hi.ToString("X2") + crc16Lo.ToString("X2");
}
Java实现CRC16算法
1、默认字符集
public static String crc16(String strData) {
byte crc16Lo, crc16Hi;
byte saveLo, saveHi;
byte[] bits = strData.getBytes(); // 使用默认字符集
crc16Hi = (byte) 0xFF;
crc16Lo = 0x00;
for (int i = 0; i < bits.length; i++) {
crc16Lo = crc16Hi;
crc16Hi = 0;
crc16Lo ^= bits[i];
for (int g = 0; g < 8; g++) {
saveHi = crc16Hi;
saveLo = crc16Lo;
crc16Hi /= 2;
crc16Lo /= 2;
if ((saveHi & 1) == 1) {
crc16Lo |= 0x80;
}
if ((saveLo & 1) == 1) {
crc16Hi ^= 0xA0;
crc16Lo ^= 0x01;
}
}
}
return String.format("%02X%02X", crc16Hi, crc16Lo);
}
2、UTF-8编码
import java.nio.charset.StandardCharsets;
public static String crc16(String strData) {
byte crc16Lo, crc16Hi;
byte saveLo, saveHi;
byte[] bits = strData.getBytes(StandardCharsets.UTF_8); // 使用UTF-8编码
crc16Hi = (byte) 0xFF;
crc16Lo = 0x00;
for (int i = 0; i < bits.length; i++) {
crc16Lo = crc16Hi;
crc16Hi = 0;
crc16Lo ^= bits[i];
for (int g = 0; g < 8; g++) {
saveHi = crc16Hi;
saveLo = crc16Lo;
crc16Hi /= 2;
crc16Lo /= 2;
if ((saveHi & 1) == 1) {
crc16Lo |= 0x80;
}
if ((saveLo & 1) == 1) {
crc16Hi ^= 0xA0;
crc16Lo ^= 0x01;
}
}
}
return String.format("%02X%02X", crc16Hi, crc16Lo);
}
3、GB2312编码
import java.nio.charset.StandardCharsets;
public static String crc16(String strData) {
if (strData == null) {
throw new IllegalArgumentException("输入字符串不能为空");
}
byte crc16Lo, crc16Hi;
byte saveLo, saveHi;
byte[] bits = strData.getBytes(StandardCharsets.GB2312); // 使用GB2312编码
crc16Hi = (byte) 0xFF;
crc16Lo = 0x00;
for (int i = 0; i < bits.length; i++) {
crc16Lo = crc16Hi;
crc16Hi = 0;
crc16Lo ^= bits[i];
for (int g = 0; g < 8; g++) {
saveHi = crc16Hi;
saveLo = crc16Lo;
crc16Hi /= 2;
crc16Lo /= 2;
if ((saveHi & 1) == 1) {
crc16Lo |= 0x80;
}
if ((saveLo & 1) == 1) {
crc16Hi ^= 0xA0;
crc16Lo ^= 0x01;
}
}
}
return String.format("%02X%02X", crc16Hi, crc16Lo);
}