C/C++給檔案加crc校驗
阿新 • 來源:網路 • 發佈:2021-04-30
概述
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;
}
歡迎關注微信公眾號:fensnote

