概述
CRC16/32校验是常用的一种校验方法,crc16需要区分多项式,不同多项式的校验结果是不一样的,
如果是对通信数据做校验,那收发两端的crc16一定要匹配,否则校验不通过。
对文件加crc校验
对文件加crc校验的的目的也是为了验证文件的完整性。添加crc校验是一种简单的验证方式。
这里用到一个小技巧:就是把文件数据的校验码追加在文件的最后,这样既不会影响文件的数据,
也不影响文件属性,并且也方便检查,不需要额外在加一个文件。
代码
#include <iostream> #include <string> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> using namespace std; /* * 附录 A:循环冗余校验(CRC)算法 * CRC 校验(Cyclic Redundancy Check)是一种数据传输错误检查方法, CRC 码两个字 * 节,包含一 16 位的二进制值。它由传输设备计算后加入到数据包中。接收设备重新计算收 * 到消息的 CRC,并与接收到的 CRC 域中的值比较,如果两值不同,则有误。 * 具体算法如下: * CRC 是先调入一值是全“1”的 16 位寄存器,然后调用一过程将消息中连续的 8 位字 * 节各当前寄存器中的值进行处理。仅每个字符中的 8Bit 数据对 CRC 有效,起始位和停止位 * 以及奇偶校验位均无效。 * CRC 校验字节的生成步骤如下: * ① 装一个 16 位寄存器,所有数位均为 1。 * ② 取被校验串的一个字节与 16 位寄存器的高位字节进行“异或”运算。运算结果放 * 入这个 16 位寄存器。 * ③ 把这个 16 寄存器向右移一位。 * ④ 若向右(标记位)移出的数位是 1,则生成多项式 1010 0000 0000 00Q01 和这个寄 * 存器进行“异或”运算;若向右移出的数位是 0,则返回③。 * ⑤ 重复③和④,直至移出 8 位。 * ⑥ 取被校验串的下一个字节 * ⑦ 重复③~⑥,直至被校验串的所有字节均与 16 位寄存器进行“异或”运算,并移位 * 8 次。 * ⑧ 这个 16 位寄存器的内容即 2 字节 CRC 错误校验码。 * 校验码按照先高字节后低字节的顺序存放。 * * * * */ unsigned short crc16(const unsigned char *ptr, int len) // ptr 为数据指针,len 为数据长度 { unsigned int i; unsigned short j,tmp,CRC16; CRC16=0xffff; for ( i = 0; i < len; i++ ) { CRC16 = *ptr ^ CRC16; for ( j = 0; j < 8; j++ ) { tmp=CRC16 & 0x0001; CRC16 =CRC16 >>1; if (tmp) CRC16=CRC16 ^ 0xa001; } *ptr++; } return(CRC16); } unsigned short checkFile( const string &file) { struct stat stFileStat; int ret = stat(file.c_str(), &stFileStat); if ( ret < 0 ) { perror("stat error"); return false; } cout<<"file size = "<<stFileStat.st_size<<endl; char *p = new char [stFileStat.st_size+2]; FILE *fp = fopen(file.c_str(), "r"); if ( fp == NULL ) { perror("fopen file error"); return -1; } ret = fread(p, stFileStat.st_size, 1, fp); if (ret != 1) { perror("fread error"); return -1; } fclose(fp); unsigned short crc16Data = crc16((unsigned char *)p, stFileStat.st_size); printf("file crc16 = 0x%04x\n", crc16Data); delete [] p; return crc16Data; } int main(int argc, char **argv) { if ( argc <= 1 ) { printf("Uage: %s <file>", argv[0]); return -1; } string file=argv[1]; if (file == "-c") { return checkFile(argv[2]); } struct stat stFileStat; int ret = stat(file.c_str(), &stFileStat); if ( ret < 0 ) { perror("stat error"); return false; } cout<<"file size = "<<stFileStat.st_size<<endl; char *p = new char [stFileStat.st_size+2]; FILE *fp = fopen(file.c_str(), "r"); if ( fp == NULL ) { perror("fopen file error"); return -1; } ret = fread(p, stFileStat.st_size, 1, fp); if (ret != 1) { perror("fread error"); return -1; } fclose(fp); unsigned short crc16Data = crc16((unsigned char *)p, stFileStat.st_size); printf("file crc16 = 0x%04x\n", crc16Data); p[stFileStat.st_size] = crc16Data & 0xff; p[stFileStat.st_size+1] = (crc16Data >> 8) & 0xff; crc16Data = crc16((unsigned char *)p, stFileStat.st_size+2); if ( crc16Data != 0) cout<<"check file crc16 fault! please add crc16 later!"<<endl; file += ".crc16"; fp = fopen(file.c_str(), "w"); if ( fp == NULL ) { perror("fopen file error"); return -1; } ret = fwrite(p, stFileStat.st_size+2, 1, fp); if (ret != 1) { perror("fwrite error"); return -1; } fclose(fp); delete [] p; cout<<"add crc16 ok! "<<endl; }