• 文件夹拷贝函数高效实现


    ////////////////////////////////////////////////////////////
    // 文件夹拷贝高效实现. 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;
    }
    
  • 相关阅读:
    Leetcode 126.单词接龙II
    Leetcode 125.验证回文串
    Leetcode 124.二叉树中的最大路径和
    Leetcode 123.买卖股票的最佳时机III
    Leetcode 122.买卖股票的最佳时机II
    西子凌波回复集5(网友整理版)
    西子凌波回复集4(网友整理版)
    西子凌波回复集3(网友整理版)
    K杀(逻辑-标准-规则)
    西子凌波49:2018年11月29日微博解盘提示
  • 原文地址:https://www.cnblogs.com/csuchao/p/2046032.html
Copyright © 2020-2023  润新知