experiment : convert a string to crc32

来源:互联网 发布:有hao123软件 编辑:程序博客网 时间:2024/05/18 15:24

今天工作任务中遇到一个分支任务, 从系统上层传来一个GUID样子的系统内唯一标识用的字符串, 传到驱动后, 只接受一个DWORD值. 想想需要将这个字符串变成DWORD, 那CRC32好了.


从CodeProject上找了一个类CCrc32Dynamic, http://www.codeproject.com/Articles/1671/CRC32-Generating-a-checksum-for-a-file

但是原版Demo是操作文件的, 算一个文件的CRC32.  改了一下CCrc32Dynamic, 添加了一个接口BufferCrc32, 来计算字符串或Buffer的CRC32值.

使用起来很方便.


工程下载点: string2crc32

使用示例:

// string2crc32.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <windows.h>#include <tchar.h>#include <string>#include <vector>#include <time.h>#include "crc/Crc32Dynamic.h"VOIDfnTest();int _tmain(int argc, _TCHAR* argv[]){size_tnCnt=0;for(nCnt = 0; nCnt < 6; nCnt++){fnTest();}/// run results/**0xfcc50d330xfcc50d330xfcc50d330xfcc50d330xfcc50d330xfcc50d33*/getchar();return 0;}VOIDfnTest(){DWORDdwCrc32=0;TCHARszMsg[_MAX_PATH];::ZeroMemory(szMsg, sizeof(szMsg));_tcscpy(szMsg, _T("12345"));/// BufferCrc32 这个接口使用起来很舒服BufferCrc32((BYTE *)szMsg, _tcslen(szMsg) * sizeof(TCHAR), dwCrc32);_tprintf(_T("0x%2x\n"), dwCrc32);}

改版的头文件

#ifndef _CRC32DYNAMIC_H_#define _CRC32DYNAMIC_H_/// original url form : http://www.codeproject.com/Articles/1671/CRC32-Generating-a-checksum-for-a-file/// modify by LostSpeedclass CCrc32Dynamic{public:CCrc32Dynamic();virtual ~CCrc32Dynamic();void Init(void);void Free(void);DWORD BufferCrc32(BYTE * lpcBuffer, size_t nLenBuffer, DWORD &dwCrc32);protected:inline void CalcCrc32(const BYTE byte, DWORD &dwCrc32) const;DWORD *m_pdwCrc32Table;};BOOL BufferCrc32(BYTE * lpcBuffer, size_t nLenBuffer, DWORD &dwCrc32);#endif

改版的实现文件

#include "stdafx.h"#include <windows.h>#include <tchar.h>#include <string>#include "Crc32Dynamic.h"//***********************************************CCrc32Dynamic::CCrc32Dynamic() : m_pdwCrc32Table(NULL){Init();}//***********************************************CCrc32Dynamic::~CCrc32Dynamic(){Free();}//***********************************************void CCrc32Dynamic::Init(void){// This is the official polynomial used by CRC32 in PKZip.// Often times the polynomial shown reversed as 0x04C11DB7.DWORD dwPolynomial = 0xEDB88320;int i, j;Free();m_pdwCrc32Table = new DWORD[256];DWORD dwCrc;for(i = 0; i < 256; i++){dwCrc = i;for(j = 8; j > 0; j--){if(dwCrc & 1)dwCrc = (dwCrc >> 1) ^ dwPolynomial;elsedwCrc >>= 1;}m_pdwCrc32Table[i] = dwCrc;}}//***********************************************void CCrc32Dynamic::Free(void){if(NULL != m_pdwCrc32Table){delete m_pdwCrc32Table;m_pdwCrc32Table = NULL;}}//***********************************************inline void CCrc32Dynamic::CalcCrc32(const BYTE byte, DWORD &dwCrc32) const{dwCrc32 = ((dwCrc32) >> 8) ^ m_pdwCrc32Table[(byte) ^ ((dwCrc32) & 0x000000FF)];}DWORD CCrc32Dynamic::BufferCrc32(BYTE * lpcBuffer, size_t nLenBuffer, DWORD &dwCrc32){_ASSERTE(lpcBuffer);DWORDdwErrorCode=NO_ERROR;size_tnCrcPos=0;dwCrc32 = 0xFFFFFFFF;try{// Is the table initialized?if(NULL == m_pdwCrc32Table)throw 0;while(nCrcPos < nLenBuffer){CalcCrc32(*(lpcBuffer + nCrcPos++), dwCrc32);}}catch(...){// An unknown exception happened, or the table isn't initializeddwErrorCode = ERROR_CRC;}dwCrc32 = ~dwCrc32;return dwErrorCode;}BOOL BufferCrc32(BYTE * lpcBuffer, size_t nLenBuffer, DWORD &dwCrc32){DWORDdwRc=0;CCrc32Dynamiccrc32;dwRc = crc32.BufferCrc32(lpcBuffer, nLenBuffer, dwCrc32);if(ERROR_CRC == dwRc){dwCrc32 = -1;}return (ERROR_CRC == dwRc) ? FALSE : TRUE;}

<2012_0812>

从网上下了一个CRC32的计算器, 看到同一个串计算出的CRC32和我做的这个实验不同.

而且我JAVA同事算出的CRC32和网上下的工具算出的相同...

有空查一下.


<2012_0825>

查到原因了, CRC32初始表和正确的CRC32初始表不一样.

正确的CRC32初始表参考 http://www.codeproject.com/Articles/1444/CRC_32, 初始化表的操作差很多.


还存在编码问题, 在Vs2008工程(我默认的工程设置是Unicode)中输入固定的字符, 比如: _T("1"), 在文件中, 读出来是0x31, 数量是1. 但是在工程中, 读出来是0x31, 0x00, 数量是2.

需要再查一下.


<2012_0826>

在CRC32之前, 将宽字符转成Ansi格式,  算出的CRC32值和网上找到的程序算出的CRC32值相同.

http://www.codeproject.com/Tips/128870/Useful-function-for-conversion-between-MBCS-and-WC


现在看看CRC16怎么算. 也想写个工具来算CRC16和CRC32, 支持文件方式和手工输入字符串.


CodeProject上有个计算各种HASH的Demo, 是计算文件HASH.

http://www.codeproject.com/Articles/3945/ReHash-A-console-based-hash-calculator


这个Demo中的算法以前用过, 只是单独搬了SHA1或MD5.

如果将这个Demo中的HASH类改改, 应该可以做一个带UI的通用HASH计算工具. 比网上找到的现有HASH工具要强大.


CHashManager算出的CRC32和网上下载的CRC32计算器结果相同.

先验证CRC16的结果正确性, 从网上找了2个CRC16计算器, 算出的结果和这个CHashManager算出的结果都不同, 倒...


sourceforge上有个开源工程, http://sourceforge.net/projects/fsumfe/, 支持96种HASH算法, 强大~

从这个工程可以得知, CRC16和CRC32都有多种算法.

CRC16包括: crc16, crc16_ccitt, crc16_ibm, crc16_x25, crc16_xmodem, crc16_zmodem
CRC32包括:crc32, crc32_bzip2, crc32_jamcrc, crc32_mpeg2


但是CHashManager算出的CRC16和fsumfe都不同...

看了algo目录中的crc16*.d文件, 看到不同的CRC16算法的不同, 初步看是CRC参考表不同, CRC算法不同.


经过多次验证, 发现网上下载的单一CRC16计算工具的算法是 crc16_zmodem,

而CHashManager算出的啥也不是~~, CRC初始表是fsumfe中定义的crc16, 但是CRC初值不同.

*uCrc16 = (*uCrc16 >> 8) ^ crc16tab[(*uCrc16 ^ *pBuffer++) & 0xFF]; ///<CHashManager

tmp = (tmp >>> 8 ) ^ crctab[(tmp ^ input[i]) & 0xFF];///< fsumfe

CRC16算法差不多, 不过, 改过来, CHashManager算出的结果也不对. 对CHashManager彻底失去兴趣...


现在可以考虑将fsumfe中的HASH算法移植成C++实现, 封装一些HASH算法组件.

这样, 在算HASH校验和时, 就可以选择MD5, SHA1, 累加和,异或和之外的多种HASH算法.


fsumfe是用D语言写的么??, 还好, 看起来和C差不多, 基本能看懂.

.d文件的资料: Source code written in the D programming language; similar to C++, but also influenced by C#, Java, and Eiffel; can be opened and edited in a text editor, but requires a D compiler to be compiled into an executable program..d


原创粉丝点击