//////////////////////////////////////////////////////////// // 文件夹拷贝高效实现. VC++6.0 控制台实现 // 作者:liujichao8567#163.com // 转载请邮件通知作者,谢谢! /////////////////////////////////////////////////////////// // 头文件包含 #include <wtypes.h> #include <winnt.h> #include <shellapi.h> #include <io.h> #include <tchar.h> #include <map> #include <string> // 设置连接器选项,不弹出控制台窗口 #pragma comment(linker, "/subsystem:windows /entry:mainCRTStartup") //////////////////////////////////////////////////////////// // 宏定义 // 返回错误码 #define RETCODE_SUCCESS 0 // 真 #define RETCODE_FAILURE -1 // 假 // 数组长度 #define _countof(a) (sizeof(a) / sizeof(a[0])) //////////////////////////////////////////////////////////// // 错误码 // 错误码表 TCHAR* g_szErrorMsgTable[] = { _T("待拷贝源文件夹不存在。"), _T("删除指定文件夹失败。"), _T("访问待删除文件夹时失败。"), _T("查找删除文件夹下子文件失败。"), _T("目的文件夹路径不正确,拷贝文件失败。"), _T("应用程序执行删除文件时操作失败。"), _T("应用程序执行拷贝文件时操作失败。") }; // 错误码起始号 #define ERROR_CODE_BEGIN_INDEX 0x10000 // 错误码ID列表 #define ACCESS_COPY_FILE_FAILURE (ERROR_CODE_BEGIN_INDEX + 0) #define DELETE_TARGET_FOLDER_FAILURE (ERROR_CODE_BEGIN_INDEX + 1) #define ACCESS_DELETE_FILE_FAILURE (ERROR_CODE_BEGIN_INDEX + 2) #define FIND_DELETE_SUBFILE_FAILURE (ERROR_CODE_BEGIN_INDEX + 3) #define TARGET_FOLDER_PATH_IS_INVALID (ERROR_CODE_BEGIN_INDEX + 4) #define EXEC_DELETE_FILE_FAILURE (ERROR_CODE_BEGIN_INDEX + 5) #define EXEC_COPY_FILE_FAILURE (ERROR_CODE_BEGIN_INDEX + 6) // 定义错误码信息结构体类型 struct ERRORINFO { std::string strFileName; // 出错源文件 int iLineNum; // 出错代码行 int iErrorCode; // 错误码 ERRORINFO() { strFileName = ""; iLineNum = -1; iErrorCode = -1; } }; ERRORINFO g_stErrorInfo; // 通过错误码ID取得对应的错误码字符串 #define GetErrorMessage(error_code) (g_szErrorMsgTable[error_code - ERROR_CODE_BEGIN_INDEX]) // 设置自定义错误 void SetLastError(int iErrCode) { // Release版本中去掉错误提示(无日志支持) #ifdef _DEBUG g_stErrorInfo.iErrorCode = iErrCode; g_stErrorInfo.strFileName = __FILE__; g_stErrorInfo.iLineNum = __LINE__; #endif } // 弹出错误信息提示对话框 void AfxErrorMessageBox() { TCHAR szErrMsg[MAX_PATH]; memset(&szErrMsg, 0, _countof(szErrMsg) * sizeof(TCHAR)); if ( -1 != g_stErrorInfo.iErrorCode ) { // 错误提示信息 wsprintf(szErrMsg, _T("源文件路径: %s\n\n代码所在行: %d\n\n错误信息: %s"), g_stErrorInfo.strFileName.c_str(), g_stErrorInfo.iLineNum, GetErrorMessage(g_stErrorInfo.iErrorCode)); // 弹出错误提示对话框 ::MessageBox(NULL, szErrMsg, _T("应用程序出错"), MB_OK | MB_ICONEXCLAMATION); } } ////////////////////////////////////////////////////// // 函数原型声明 BOOL CopyFolder(LPCTSTR lpszExistingFolderName, LPCTSTR lpszNewFolderName, BOOL bOverWrite); BOOL DeleteFolder(LPCTSTR lpszExistringFolderName, BOOL bOnlyChild); ////////////////////////////////////////////////////////// // 主函数入口 int main(int argc, char* argv[]) { if ( !CopyFolder("D:\\1", "G:\\DB", TRUE) ) { AfxErrorMessageBox(); return -1; } return 0; } /////////////////////////////////////////////////////////////// // 函数实现 // 文件夹拷贝函数 // lpszExistingFolderName : 源文件夹 // lpszNewFolderName : 宿文件夹 // bOverWrite : 是否覆盖标记 // return : 拷贝成功返回true,失败返回false BOOL CopyFolder(LPCTSTR lpszExistingFolderName, LPCTSTR lpszNewFolderName, BOOL bOverWrite) { // 源文件夹不存在 if ( RETCODE_FAILURE == ::access(lpszExistingFolderName, 0) ) { SetLastError(ACCESS_COPY_FILE_FAILURE); return FALSE; } // 目标文件夹存在 if ( RETCODE_SUCCESS == ::access(lpszNewFolderName, 0) ) { // 覆盖模式下,先行删除目的文件夹内容 if ( bOverWrite ) { if ( !DeleteFolder(lpszNewFolderName, TRUE) ) { SetLastError(DELETE_TARGET_FOLDER_FAILURE); return FALSE; } } } else { // 创建目的文件夹 if ( !::CreateDirectory(lpszNewFolderName, NULL) ) { SetLastError(TARGET_FOLDER_PATH_IS_INVALID); return FALSE; } } // 构造拷贝命令 SHFILEOPSTRUCT sh; memset(&sh, 0, sizeof(SHFILEOPSTRUCT)); sh.wFunc = FO_COPY; sh.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI; sh.pFrom= lpszExistingFolderName; sh.pTo = lpszNewFolderName; // 执行命令 if ( RETCODE_FAILURE == ::SHFileOperation(&sh) ) { SetLastError(EXEC_COPY_FILE_FAILURE); return FALSE; } return TRUE; } // 文件夹删除函数 // lpszExistringFolderName : 待删除文件夹路径 // bOnlyChild : 是否仅删除子文件/文件夹标记 // return : 删除成功返回true,失败返回false BOOL DeleteFolder(LPCTSTR lpszExistringFolderName, BOOL bOnlyChild) { // 判断待删除文件夹是否存在 if ( RETCODE_FAILURE == ::access(lpszExistringFolderName, 0) ) { SetLastError(ACCESS_DELETE_FILE_FAILURE); return FALSE; } // 仅删除子文件和子文件夹 if ( bOnlyChild ) { WIN32_FIND_DATA stFileInfo; memset(&stFileInfo, 0, sizeof(WIN32_FIND_DATA)); // 查找第一个文件 TCHAR szPath[MAX_PATH]; memset(&szPath, 0, _countof(szPath) * sizeof(TCHAR)); wsprintf(szPath, _T("%s\\%s"), lpszExistringFolderName, _T("*.*")); HANDLE hFile = FindFirstFile(szPath, &stFileInfo); if ( INVALID_HANDLE_VALUE == hFile ) { SetLastError(FIND_DELETE_SUBFILE_FAILURE); return FALSE; } // 遍历所有文件 do { // 过滤系统文件夹 if ( '.' == stFileInfo.cFileName[0] ) { continue; } // 删除文件/文件夹 else { memset(&szPath, 0, _countof(szPath) * sizeof(TCHAR)); wsprintf(szPath, _T("%s\\%s"), lpszExistringFolderName, stFileInfo.cFileName); if ( !DeleteFolder(szPath, FALSE) ) { SetLastError(DELETE_TARGET_FOLDER_FAILURE); return FALSE; } } } while (::FindNextFile(hFile, &stFileInfo) ); ::FindClose(hFile); } else { // 构造删除命令 SHFILEOPSTRUCT sh; memset(&sh, 0, sizeof(SHFILEOPSTRUCT)); sh.wFunc = FO_DELETE; sh.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI; sh.pFrom = lpszExistringFolderName; // 执行删除操作 if ( RETCODE_FAILURE == ::SHFileOperation(&sh) ) { SetLastError(EXEC_DELETE_FILE_FAILURE); return FALSE; } } return TRUE; }