cocos2d 实现的md5模块

小笔记第五弹。

cocos2d-x在3.15以上版本中添加了获取文件md5值的功能。在external目录下多了一个md5文件夹,里面就是实现获取文件md5值的方法。

原理就是先把文件读取进来,处理成unsigned char*格式,然后调用md5类的相关方法。引擎的cocos目录下的base目录,有ccutils.h和ccutils.cpp文件,这个类添加了getFileMD5Hash方法,调用就可以获取文件的md5。分析一下调用原理:

首先还是读取文件。将读取到的文件写入cocos2d::Data类型数据下,cocos2d::Data类型也就是封装了unsigned char*和size_t两个数据,这里FileUtils::getInstance()->getContents(filename, &data)调用的方式有点不一样,首先将Data类型的数据利用FileUtils类中的getContents的模版方法,调用了ResizableBufferAdapter这个特例化类模版,将传入的Data型参数作为ResizableBufferAdapter类的成员变量,然后在调用自己的getContents方法读取文件,并将文件的内容写入Data型数据中。其中的调用有点曲折复杂,如果想将cocos的这部分md5功能提取出来的话,不用声明这个类模版,只要把其中的数据类型弄明白了,就可以了。

以下是本人改写的cocos封装的md5功能,基本思路都是cocos的,我只是代码的搬运工(手动捂脸):

std::string md5Str = "";
//filename 应该包含完整路径的文件名,否则应该补全路径,参考cocos->base->FileUtils的fullPathForFilename方法
std::string filename = "
这里是文件全路径";
if (filename.empty())
{
md5Str = "filename is empty";
std::cout << md5Str << std::endl;
return;
}
//二进制读写打开文件
FILE* fp = fopen(filename.c_str(), "rb");
if (fp == nullptr)
{
md5Str = "open file fail";
std::cout << md5Str << std::endl;
return;
}
#if defined(_MSC_VER)
auto descriptor = _fileno(fp);
#else 
auto descriptor = fileno(fp);
#endif
struct stat statBuff;
//fstat 文件句柄和stat结构体作为参数,将文件标识符写入stat结构体,成功返回0,失败返回-1
if (fstat(descriptor, &statBuff) == -1)
{
fclose(fp);
md5Str = "parse file fail";
std::cout << md5Str << std::endl;
return;
}


//文件内容存的地方
unsigned char* myData=nullptr;
size_t myDataSize=0;


size_t buffSize = statBuff.st_size;
//myData->resize(buffSize);
if (myDataSize < buffSize)
{
void* tempBuff = realloc(myData, buffSize);
if (tempBuff)
{
myData = (unsigned char*)tempBuff;
myDataSize = buffSize;
}
}
//fread函数,读取文件流到指定存储位置,1表示读取一个项,buffSize表示每个项buffSize字节
size_t readSize = fread(myData, 1, buffSize, fp);
fclose(fp);
if (readSize < buffSize)
{
//读取文件后,读取到的字节数比文件描述结构体里面的字节数小,表示文件读取失败
// if (myDataSize < readSize)
// {
// void* tempBuff = realloc(myData, readSize);
// if (tempBuff)
// {
// myData = (unsigned char*)tempBuff;
// myDataSize = readSize;
// }
// }
myData = nullptr;
myDataSize = 0;
md5Str = "read file failed";
std::cout << md5Str << std::endl;
return;


}


//文件读取完毕,下面开始执行md5逻辑
static const unsigned int MD5_DIGEST_LENGTH=16;
md5_state_t myState;
md5_byte_t myDigest[MD5_DIGEST_LENGTH];
char hexOutPut[(MD5_DIGEST_LENGTH << 1) + 1] = { 0 };


md5_init(&myState);
md5_append(&myState, (const md5_byte_t*)myData, myDataSize);
md5_finish(&myState, myDigest);


for (int di = 0; di < 16; ++di)
{
sprintf(hexOutPut + di * 2, "%02x", myDigest[di]);
}
md5Str = "md5 success";
std::cout << md5Str << std::endl;
return;


最后这个hexOutPut 里面存放的就是32位的md5值,多出来一位是结尾\0。

最后的最后,.h和.c的文件添加到预编译头的c++工程时,将.c文件的属性里面的预编译头功能关掉。

最后的最后的最后,fopen和sprintf方法警告不安全,需要使用fopen_s和sprintf_s时,在工程属性里面的预处理定义里面添加宏定义_CRT_SECURE_NO_WARNINGS就可以关掉这个警告。

n个最后,代码纯手工整理,引用请注明出处。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值