最近客戶有CRC校驗的需求,即但願Android端對字符串進行校驗,並將生成的2個字節的CRC校驗碼追加到字符串中,而後一塊兒寫入文件。當系統聯網後,會經過寫入的字符串去向服務器請求設備序列號,服務器會根據該字符串的原始字符串(不含校驗碼)進行校驗,若是校驗出來的值跟最後兩個字節的校驗碼匹配上,則下發一個序列號,不然爲空。數組
CRC的校驗方式多種多樣,每一個客戶都有本身的校驗方式。這次客戶提供了C語言版本的校驗方式,這邊要將C語言版本的校驗轉化爲Java版本。安全
但因爲C語言和Java的基本類型對不上,如C語言的變量類型有符號之分,而Java則統一都帶符號,並無所謂的無符號類型變量。若未接觸過的同窗可能要費點時間去作轉化,這裏給出轉化的技巧。服務器
這裏先上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校驗都會有一個碼錶,用於生成校驗碼。post
因爲C語言有有符號和無符號之分,而Java則沒有這種區分,那麼在轉化的時候,要注意符號的問題。這裏有個技巧,轉化時,C語言和Java的類型對應關係以下:動畫
int->int
short->int
char*->String/byte[]
char->short
複製代碼
什麼意思?即C語言使用int類型的變量時,Java也使用int類型變量,C語言使用short類型變量時,Java使用int類型變量。。。spa
貼上Java的CRC校驗代碼,你們對照着看就明白:3d
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進制字節進行校驗的,有針對字符進行校驗的,好比須要校驗以下內容:code
0001020304050607
複製代碼
那麼這時須要確認清楚,究竟是校驗字節,仍是逐個字符的進行校驗。本文則是逐個字符進行校驗。cdn
CRC校驗多見於通信協議中,會對通信內容進行校驗,而後將生成的校驗碼追加到通信幀中。也有像本文這樣子的,對某個文件中的內容進行校驗,而後生成校驗碼,提升安全性。
若是文章存在錯誤描述,可直接留言,一塊兒探討!
我在微信公衆號也有寫文章,更新比較及時,有興趣者能夠掃描以下二維碼,或者微信搜索【Android系統實戰開發】,關注有驚喜哦!