检测重复文件功能实现(改进版本1)
2014-04-14 00:14
288 查看
针对大文件md5计算时间偏长问题,觉得不需要完全计算整个文件的md5也可以初步确定文件是否相同。换作计算一些属性的md5值,极大提高速度,也可以满足需求:
1. 文件名
2. 文件修改时间——根据实验,两个重复文件如果仅仅是复制,创建时间和最后访问时间都会改变,但最后修改时间在内容没有修改时不会是变的。这是根据文件系统特征决定的。
3. 文件大小
以上三点使用以下结构来表示。typedef struct FileInfoForCompare
{
DWORD dwFileAttributes;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
WCHAR cFileName[ 260 ];
}FileInfoForCompare_;
以下版本更改计算md5的数据,更正了GetMultimapForDirList函数的while循环没有把迭代器加1的bug。改进之后的代码如下:
#include <windows.h>
#include "md5.h"
typedef struct MIX_WIN32_FIND_DATA
{
std::wstring fullpath;
WIN32_FIND_DATA wfd;
}MIX_WIN32_FIND_DATA_;
typedef std::multimap<INT64,MIX_WIN32_FIND_DATA> map_type;
typedef std::list<std::wstring> list_type;
union union_MD5
{
INT64 i64_md5;
unsigned char c_md5[16];
};
typedef struct FileInfoForCompare
{
DWORD dwFileAttributes;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
WCHAR cFileName[ 260 ];
}FileInfoForCompare_;
void GetMd5(MIX_WIN32_FIND_DATA &mwfd,union_MD5 &uMd5)
{
// use file data md5.
//MD5File(mwfd.fullpath.c_str(), uMd5.c_md5);
// use file attribute md5
FileInfoForCompare fic;
fic.dwFileAttributes = mwfd.wfd.dwFileAttributes;
fic.ftLastWriteTime = mwfd.wfd.ftLastWriteTime;
fic.nFileSizeHigh = mwfd.wfd.nFileSizeHigh;
fic.nFileSizeLow = mwfd.wfd.nFileSizeLow;
_tcscpy_s(fic.cFileName,MAX_PATH,mwfd.wfd.cFileName);
MD5Data((unsigned char*)(&fic),sizeof(fic),uMd5.c_md5);
}
DWORD RecurseGetFileList(std::wstring &fullpath,map_type &map_data)
{
DWORD count = 0;
MIX_WIN32_FIND_DATA mwfd;
WIN32_FIND_DATA &fd = mwfd.wfd;
HANDLE hFile = ::FindFirstFile(fullpath.c_str(),&fd);
if ( INVALID_HANDLE_VALUE == hFile )
{
return 0;
}
do
{
if ( ( 0 != _tcscmp(fd.cFileName,_T(".")))
&& ( 0 != _tcscmp(fd.cFileName,_T("..")) ) )
{
if ( fd.dwFileAttributes == INVALID_FILE_ATTRIBUTES )
{
return 0;
}
if ( FILE_ATTRIBUTE_DIRECTORY & fd.dwFileAttributes )
{
std::wstring newdir = fullpath.substr(0,fullpath.length()-2);
newdir.append(_T("\\")).append(fd.cFileName).append(_T("\\*"));
count += RecurseGetFileList(newdir,map_data);
}
else
{
union_MD5 uMd5;
mwfd.fullpath = fullpath.substr(0,fullpath.length()-2);
mwfd.fullpath.append(_T("\\")).append(fd.cFileName);
GetMd5(mwfd,uMd5);
map_data.insert(std::make_pair(uMd5.i64_md5,mwfd));
int lowpart = uMd5.i64_md5>>32;
int highpart = uMd5.i64_md5&0xFFFFFFFF;
_tprintf(_T("MD5:%04x %04x filepath: %s\n"),highpart,lowpart,mwfd.fullpath.c_str());
count++;
}
}
if (::FindNextFile(hFile,&fd) == FALSE)
{
break;
}
}while(1);
return count;
}
DWORD GetMultimapForDirList(list_type dirlist,map_type &out_map)
{
DWORD count = 0;
WIN32_FILE_ATTRIBUTE_DATA fad;
list_type::iterator it = dirlist.begin();
while (it!=dirlist.end())
{
count += RecurseGetFileList(*it,out_map);
it++;
}
return count;
}
int main(int argc,char ** argv)
{
list_type find_list;
map_type find_map;
find_list.push_front(std::wstring(_T("D:\\Setup Files\\*")));
GetMultimapForDirList(find_list,find_map);
return 0;
}
1. 文件名
2. 文件修改时间——根据实验,两个重复文件如果仅仅是复制,创建时间和最后访问时间都会改变,但最后修改时间在内容没有修改时不会是变的。这是根据文件系统特征决定的。
3. 文件大小
以上三点使用以下结构来表示。typedef struct FileInfoForCompare
{
DWORD dwFileAttributes;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
WCHAR cFileName[ 260 ];
}FileInfoForCompare_;
以下版本更改计算md5的数据,更正了GetMultimapForDirList函数的while循环没有把迭代器加1的bug。改进之后的代码如下:
#include <windows.h>
#include "md5.h"
typedef struct MIX_WIN32_FIND_DATA
{
std::wstring fullpath;
WIN32_FIND_DATA wfd;
}MIX_WIN32_FIND_DATA_;
typedef std::multimap<INT64,MIX_WIN32_FIND_DATA> map_type;
typedef std::list<std::wstring> list_type;
union union_MD5
{
INT64 i64_md5;
unsigned char c_md5[16];
};
typedef struct FileInfoForCompare
{
DWORD dwFileAttributes;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
WCHAR cFileName[ 260 ];
}FileInfoForCompare_;
void GetMd5(MIX_WIN32_FIND_DATA &mwfd,union_MD5 &uMd5)
{
// use file data md5.
//MD5File(mwfd.fullpath.c_str(), uMd5.c_md5);
// use file attribute md5
FileInfoForCompare fic;
fic.dwFileAttributes = mwfd.wfd.dwFileAttributes;
fic.ftLastWriteTime = mwfd.wfd.ftLastWriteTime;
fic.nFileSizeHigh = mwfd.wfd.nFileSizeHigh;
fic.nFileSizeLow = mwfd.wfd.nFileSizeLow;
_tcscpy_s(fic.cFileName,MAX_PATH,mwfd.wfd.cFileName);
MD5Data((unsigned char*)(&fic),sizeof(fic),uMd5.c_md5);
}
DWORD RecurseGetFileList(std::wstring &fullpath,map_type &map_data)
{
DWORD count = 0;
MIX_WIN32_FIND_DATA mwfd;
WIN32_FIND_DATA &fd = mwfd.wfd;
HANDLE hFile = ::FindFirstFile(fullpath.c_str(),&fd);
if ( INVALID_HANDLE_VALUE == hFile )
{
return 0;
}
do
{
if ( ( 0 != _tcscmp(fd.cFileName,_T(".")))
&& ( 0 != _tcscmp(fd.cFileName,_T("..")) ) )
{
if ( fd.dwFileAttributes == INVALID_FILE_ATTRIBUTES )
{
return 0;
}
if ( FILE_ATTRIBUTE_DIRECTORY & fd.dwFileAttributes )
{
std::wstring newdir = fullpath.substr(0,fullpath.length()-2);
newdir.append(_T("\\")).append(fd.cFileName).append(_T("\\*"));
count += RecurseGetFileList(newdir,map_data);
}
else
{
union_MD5 uMd5;
mwfd.fullpath = fullpath.substr(0,fullpath.length()-2);
mwfd.fullpath.append(_T("\\")).append(fd.cFileName);
GetMd5(mwfd,uMd5);
map_data.insert(std::make_pair(uMd5.i64_md5,mwfd));
int lowpart = uMd5.i64_md5>>32;
int highpart = uMd5.i64_md5&0xFFFFFFFF;
_tprintf(_T("MD5:%04x %04x filepath: %s\n"),highpart,lowpart,mwfd.fullpath.c_str());
count++;
}
}
if (::FindNextFile(hFile,&fd) == FALSE)
{
break;
}
}while(1);
return count;
}
DWORD GetMultimapForDirList(list_type dirlist,map_type &out_map)
{
DWORD count = 0;
WIN32_FILE_ATTRIBUTE_DATA fad;
list_type::iterator it = dirlist.begin();
while (it!=dirlist.end())
{
count += RecurseGetFileList(*it,out_map);
it++;
}
return count;
}
int main(int argc,char ** argv)
{
list_type find_list;
map_type find_map;
find_list.push_front(std::wstring(_T("D:\\Setup Files\\*")));
GetMultimapForDirList(find_list,find_map);
return 0;
}
相关文章推荐
- 检测重复文件功能实现
- js版本的文本文件文件保存编码自动检测功能实现与检测原理
- Python通过MD5值实现重复文件的检测
- 织梦57版本发布和修改检测文章标题重复的功能
- 使用DFSClient实现 hadoop上传文件功能,采用使用输入输出流实现 Hadoop 版本2.7.0
- 通过操作BMP文件的RGB值实现BMP文件的旋转,锐化,二值化,轮廓提取,边缘检测,合并等功能(一)
- 通过操作BMP文件的RGB值实现BMP文件的旋转,锐化,二值化,轮廓提取,边缘检测,合并等功能(二)
- shell脚本实现查找文件夹下重复的文件,并提供删除功能
- Linux环境用C语言实现读取配置文件来区分产品的多个版本以及多个功能
- httpd-2.2及httpd-2.4版本实现对文件和用户的权限管理以及网页的https的功能
- Python实现检测文件的MD5值来查找重复文件
- 使用DFSClient实现 hadoop上传文件功能,采用使用输入输出流实现 Hadoop 版本2.7.0
- shell脚本实现查找文件夹下重复的文件,并提供删除功能
- Sruts2下实现多文件上传功能(后台上传app软件,做版本更新)
- 用thinkphp实现上传文件到数据库的功能并且文件内容不可以重复
- 使用jquery 实现 仿google 的智能提示输入框功能 (改进版本)
- 巧用DBGrid控件的Sort属性实现“点击标题栏自动排序功能”。(改进版本)
- 完成一个学生管理程序,使用学号作为键添加5个学生对象,并可以将全部信息保存在文件中,可以实现对学生信息的学号查找,输出全部学生信息的功能。
- 安卓检测用户吹气功能的实现:吹一吹
- Python实现的txt文件去重功能示例