根据需求,写了个简易版的类MD5er,一个类相当于对应一个文件夹,用来判断两个文件夹下的文件是否相等[暂不能读取目录下的子目录下的内容],主要函数包括:
1.MD5er(str):初始化实例,将文件夹地址设置为str。
2.GetFileName():获取文件夹下的所有文件名。
3.CodeMd5():对每个文件名生成对应的Md5码。
4.get_file_md5(str) [别处copy过来的]:根据输出的字符串(文件名),计算MD5。
6.一个==的运算符重载,用于判断两个MD5er的实例,也即两个文件夹,其下所有文件的MD5是否都相同。
成员变量:
1.file2MD5,一个map,其key:value对分别为文件名和他的MD5码。
2.dirname,指定目录的地址。
3.IgnoreFile,用于指定不参与计算、比较的文件名的集合。
类的定义如下:
#include <fstream>
#include <openssl/md5.h>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <set>
#include <dirent.h>
using std::string;
using namespace std;
class MD5er{
private:
map<string, string> file2MD5; //文件名到MD5码的映射
string dirname ;//文件夹名
set<string> IgnoreFile;//不参与计算MD5码、比较的文件名
public:
MD5er(string const str){
dirname=str;
IgnoreFile.insert("log.txt");
IgnoreFile.insert("pkgtest.csv");
}
void GetFileName(){ //获取路径下的文件名,放入file2MD5
DIR *dp = NULL;
dp = opendir(dirname.c_str());
struct dirent *dirp;
while ((dirp = readdir(dp))) {
if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0|| IgnoreFile.find(dirp->d_name)!=IgnoreFile.end())
continue;//如果是./.. 或文件名在IgnoreFile中,则跳过
file2MD5[dirp->d_name]="";
}
closedir(dp);
}
void CodeMD5(){
map<string,string>::iterator it;
for(it = file2MD5.begin();it!=file2MD5.end();it++){
it->second=get_file_md5(dirname+"/"+it->first); //计算每个文件名的MD5码
}
}
string get_file_md5(const string &file_name)
{
string md5value;
ifstream file(file_name.c_str(), ifstream::binary);
MD5_CTX md5Context;
MD5_Init(&md5Context);
char buf[1024 * 16];
while (file.good()) {
file.read(buf, sizeof(buf));
MD5_Update(&md5Context, buf, file.gcount());
}
unsigned char result[MD5_DIGEST_LENGTH];
MD5_Final(result, &md5Context);
char hex[35];
memset(hex, 0, sizeof(hex));
for (int i = 0; i < MD5_DIGEST_LENGTH; ++i)
{
sprintf(hex + i * 2, "%02x", result[i]);
}
hex[32] = '\0';
md5value = string(hex);
return md5value;
}
void addIgnoreFile(string str){
IgnoreFile.insert(str);
}
bool operator==(MD5er &dir2){// == 的重载 判断两个MD5er类(文件夹)的文件MD5码是否相同
map<string,string>::iterator it;
set<string>::iterator itset;
set<string> allFileName;
bool ret=true;
for(it = this->file2MD5.begin();it!=this->file2MD5.end();it++){
allFileName.insert(it->first);
}
for(it = dir2.file2MD5.begin();it!=dir2.file2MD5.end();it++){
allFileName.insert(it->first);//用来存两个文件夹下的所有文件名
}
for(itset=allFileName.begin();itset!=allFileName.end();itset++){
if(this->file2MD5.find(*itset)==this->file2MD5.end()){
ret=false;//如果第一个文件夹找不到该文件
}
else if(dir2.file2MD5.find(*(itset))==dir2.file2MD5.end()){
ret=false;//如果第二个文件夹找不到该文件
}
else{
if(this->file2MD5[(*itset)]==dir2.file2MD5[(*itset)]){
ret=false;//两个文件夹都找到该文件,但是MD5码不等
}
}
}
return ret;
}
};
编译及运行方法:
g++ test.cpp -o testmd5 -lcrypto -lssl
./testmd5
运行结果:
int main(int argc, char* argv[])
{
MD5er dir1= MD5er("/home/type/sparse_point_mapping/result_record/spa_result_2021-05-29-10-15-49");
MD5er dir2= MD5er("/home/type/sparse_point_mapping/result_record/spa_result_2021-05-31-14-04-34");
dir1.GetFileName();
dir2.GetFileName();
dir1.CodeMD5();
dir2.CodeMD5();
dir1.PrintFile2MD5();
dir2.PrintFile2MD5();
cout<<(dir1==dir2);
return 0;
}
------------------Function PrintFile2MD5------------------
the directory PATH is :/home/type/sparse_point_mapping/result_record/spa_result_2021-05-29-10-15-49
`````
File Name MD5
map_info.txt 5025129ec233bcd1355472063f88b521
map_info.yaml 78834eafad9ba45616d2b13f689449be
semantic_map_final.bin 009e9249fa29b2c4af88764c2f0c36d1
semantic_map_final.obj 1c26e51f5bc42090ff2d7d2350341921
semantic_map_incremental.callback.obj e19e116ae62cc13e3f9b6a481977c5aa
sparse_map_camera_cameraB195.bin f18a6375a0b47d730d61ef1a58ea5c6e
sparse_map_camera_cameraF195.bin e6a879b40965b9993cbd661398f70499
sparse_map_camera_cameraL195.bin e64804f78b81f4988210472d32db7673
sparse_map_camera_cameraR195.bin 3d9d0c05bc689b0cfa4c5f336000635e
sparse_map_final.obj a2d8c1f8e62528aca5d2468cc4537892
sparse_map_incremental.callback.obj 734685bf04cd62e3ad2d21028c81104d
trajectory.callback.obj e7c62c449e3893dfaba290146ac345e0
trajectory.callback.txt c6ae0598679403bb1dfd76cf0fe41acb
`````
------------------Function PrintFile2MD5------------------
the directory PATH is :/home/type/sparse_point_mapping/result_record/spa_result_2021-05-31-14-04-34
`````
File Name MD5
map_info.txt 5025129ec233bcd1355472063f88b521
map_info.yaml 78834eafad9ba45616d2b13f689449be
semantic_map_final.bin 009e9249fa29b2c4af88764c2f0c36d1
semantic_map_final.obj 1c26e51f5bc42090ff2d7d2350341921
semantic_map_incremental.callback.obj e19e116ae62cc13e3f9b6a481977c5aa
sparse_map_camera_cameraB195.bin f18a6375a0b47d730d61ef1a58ea5c6e
sparse_map_camera_cameraF195.bin e6a879b40965b9993cbd661398f70499
sparse_map_camera_cameraL195.bin e64804f78b81f4988210472d32db7673
sparse_map_camera_cameraR195.bin 3d9d0c05bc689b0cfa4c5f336000635e
sparse_map_final.obj a2d8c1f8e62528aca5d2468cc4537892
sparse_map_incremental.callback.obj 734685bf04cd62e3ad2d21028c81104d
trajectory.callback.obj e7c62c449e3893dfaba290146ac345e0
trajectory.callback.txt c6ae0598679403bb1dfd76cf0fe41acb
`````
File[map_info.txt]:Matched!
File[map_info.yaml]:Matched!
File[semantic_map_final.bin]:Matched!
File[semantic_map_final.obj]:Matched!
File[semantic_map_incremental.callback.obj]:Matched!
File[sparse_map_camera_cameraB195.bin]:Matched!
File[sparse_map_camera_cameraF195.bin]:Matched!
File[sparse_map_camera_cameraL195.bin]:Matched!
File[sparse_map_camera_cameraR195.bin]:Matched!
File[sparse_map_final.obj]:Matched!
File[sparse_map_incremental.callback.obj]:Matched!
File[trajectory.callback.obj]:Matched!
File[trajectory.callback.txt]:Matched!
The files are exactly the same!