vlambda博客
学习文章列表

C语言的CRC校验如何转化为Java CRC校验?

前言

CRC校验在嵌入式开发中很常见,特别是在通讯协议中尤为常见。但这次客户是想对某一字符串进行校验,然后追加校验值,再写到某一文件中。

概述

CRC的校验方式多种多样,每个客户都有自己的校验方式。此次客户提供了C语言版本的校验方式,这边要将C语言版本的校验转化为Java版本。

但由于C语言和Java的基本类型对不上,如C语言的变量类型有符号之分,而Java则统一都带符号,并没有所谓的无符号类型变量。若未接触过的同学可能要费点时间去做转化,这里给出转化的技巧。

C语言版本的校验

这里先上C语言版本的校验,代码如下:

unsigned short int CRC_TABLE[16]={0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7,
0x8108,0x9129,0xA14A,0xB16B,0xC18C,0xD1AD,0xE1CE,0xF1EF};

unsigned int getCRC( char *pbuffer, unsigned int buff_len)
{
unsigned short int mCRC;
unsigned char mTemp;

mCRC=0x0;

while(buff_len--)
{
mTemp=(unsigned char)(mCRC>>0x0C);
mCRC<<=4;
mCRC^=CRC_TABLE[mTemp^((*pbuffer)>>0x04)];
mTemp=(unsigned char)(mCRC>>0x0C);
mCRC<<=4;
mCRC^=CRC_TABLE[mTemp^((*pbuffer)&0x0F)];
pbuffer++;
}

return (unsigned int)mCRC;
}

一般CRC校验都会有一个码表,用于生成校验码。

由于C语言变量有有符号和无符号之分,而Java则没有这种区分,那么在转化的时候,要注意符号的问题。这里有个技巧,转化时,C语言和Java的类型对应关系如下:

int->int
short->int
char*->String/byte[]
char->short

什么意思?即C语言使用int类型的变量时,Java也使用int类型变量,C语言使用short类型变量时,Java使用int类型变量。。。

Java版本的CRC校验

贴上Java的CRC校验代码,大家对照着看就明白:

private byte[] getCRC16(String data) {
int crc = 0x0; //这里只需用到int的低16位即可
short tem = 0x00;
char[] ch = data.toCharArray();
for (char c : ch) {
byte b = (byte)c;
tem = (short)((crc >> 0x0c) & 0x00ff);
crc <<= 4;
crc &= 0x0000ffff; //保证高16位一直为0
crc ^=crc16tab[(tem ^ (b >> 0x04))&0x000000ff]; //获取高八位CRC校验码
crc &= 0x0000ffff;
tem = (short)((crc >> 0x0c) & 0x00ff);
crc <<= 4;
crc &= 0x0000ffff;
crc ^= crc16tab[(tem ^ (b & 0x0f)) & 0x000000ff]; //获取低八位CRC校验码
crc &= 0x0000ffff;//只需低16位的CRC校验码
}

byte[] res = intToByteArray(crc);//将int类型转为byte数组

return res;
}

需要注意的是,在CRC校验中,有针对16进制字节进行校验的,有针对字符进行校验的,比如需要校验如下内容:

0001020304050607

那么这时需要确认清楚,到底是校验字节,还是逐个字符的进行校验。本文则是逐个字符进行校验。

结语

CRC校验多见于通讯协议中,会对通讯内容进行校验,然后将生成的校验码追加到通讯帧中。也有像本文这样子的,对某个文件中的内容进行校验,然后生成校验码,提高安全性。

你可能还想看