文件/文件夹操作函数封装(使用SHFileOperation和SHCreateDirectory函数实现)

       最近工作中涉及到很多文件和文件夹的处理,包括删除、检测是否存在、移动、复制等,用过CopyFile、MoveFile等函数,也使用过SHFIleOperation()函数,觉得后者比较好用些,参考了CSDN其他一些前辈的关于文件、文件夹操作的总结,与其他相关网站搜集到的资料,个人总结并封装了一些基本操作函数(注:其中部分函数为其他前辈总结,个人只是进行了验证与一些调整,由于无法查找到引用的原始网址,敬请见谅),介绍如下:


       注:在经过实际使用测试后,发现一个经常出现的Bug,即SHFileOperation操作时经常提示“无法操作文件,无法读取源文件或磁盘”,后经查询与验证,此错误原因在于SHFILEOPSTRUCT FileOp结构体中pTo和pFrom赋值必须加上"\0",否则出错,因此在SHCopyFile等函数中做了修改,敬请注意。


#include <shellapi.h>

///
// C++文件/文件夹操作相关函数
// 1.检测文件/文件夹是否存在
// 2.获取文件/文件夹全路径,如果是文件夹,就加上"\\"
// 3.删除、拷贝、移动、重命名文件/文件夹

// 1.检测文件/文件夹是否存在
// _access函数,函数原型为 int _access( const char *path, int mode );
// CreateFile函数;
// FindFirstFile函数;
// GetFileAttributes函数;
// Shell Lightweight Utility APIs函数 PathFileExists():专门判断文件和目录是否存在的函数
// Header: Declared in Shlwapi.h Import Library: Shlwapi.lib
BOOL FileExists(LPCTSTR lpszFileName)  
{  
    DWORD dwAttributes = GetFileAttributes(lpszFileName);  
    if(dwAttributes == 0xFFFFFFFF)  
    {  
        return false;  
    }   
  
    return TRUE;  
}  

// 2.获取文件/文件夹全路径,如果是文件夹,就加上"\\"(未完成)
BOOL GetFileFullDirectoryPath(CString &szPath)  
{  
    DWORD dwAttibute;  
    dwAttibute= GetFileAttributes(szPath);  

    if (dwAttibute != 0xFFFFFFFF)  
    {  
        if ((dwAttibute&FILE_ATTRIBUTE_DIRECTORY) != 0)  
        {  
            if (szPath.Right(1) != '\\')  
            {  
                szPath += "\\";  
            }  
            return TRUE;  
        }  
    }  
    return FALSE;  
}  

// 3.删除、拷贝、移动、重命名文件/文件夹
#include <windows.h>
#include <stdio.h>

// 删除文件或者文件夹
BOOL SHDeleteFile(TCHAR *lpszPath)
{
/*
BOOL SHDeleteFile(CString strPath)
{
	LPCTSTR lpszPath = LPCTSTR(strPath.GetBuffer());
*/
    // SHFileOperation函数参数中,pTo和pFrom都应当有"\0"结尾,
    // 否则容易出现无法读取源文件或磁盘错误,尤其是pFrom必须有;
    TCHAR lpszPathnew[MAX_PATH * 2] = {0};

    lstrcpy(lpszPathnew, lpszPath);

	SHFILEOPSTRUCT FileOp = {0};

	// FileOp.hwnd = GetSafeHwnd();
	FileOp.fFlags = FOF_ALLOWUNDO   	 //允许放回回收站
					|FOF_NOCONFIRMATION; //不出现确认对话框
	FileOp.pFrom = lpszPathnew;
	FileOp.pTo = NULL;  //一定要是NULL
	FileOp.wFunc = FO_DELETE;  //删除操作

	return (SHFileOperation(&FileOp) == 0);
}

// 复制文件或文件夹
BOOL SHCopyFile(TCHAR *pTo, TCHAR *pFrom)
{
/*
BOOL SHDeleteFile(CString strPathTo, CString strPathFrom)
{
	LPCTSTR pTo = LPCTSTR(strPathTo.GetBuffer());
	LPCTSTR pFrom = LPCTSTR(strPathFrom.GetBuffer());
*/
    TCHAR pFileTo[MAX_PATH * 2] = {0};
    TCHAR pFileFrom[MAX_PATH * 2] = {0};

    lstrcpy(pFileFrom, pFrom);
    lstrcpy(pFileTo, pTo);

	SHFILEOPSTRUCT FileOp = {0};

	// FileOp.hwnd = GetSafeHwnd();
	FileOp.fFlags = FOF_NOCONFIRMATION   //不出现确认对话框
					|FOF_NOCONFIRMMKDIR  //需要时直接创建一个文件夹,不需用户确定
					|FOF_SIMPLEPROGRESS; //进度条
	FileOp.pFrom = pFileFrom;
	FileOp.pTo = pFileTo;
	FileOp.wFunc = FO_COPY;

	return (SHFileOperation(&FileOp) == 0);
}

// 移动文件或文件夹
BOOL SHMoveFile(TCHAR *pTo, TCHAR *pFrom)
{
/*
BOOL SHDeleteFile(CString strPathTo, CString strPathFrom)
{
	LPCTSTR pTo = LPCTSTR(strPathTo.GetBuffer());
	LPCTSTR pFrom = LPCTSTR(strPathFrom.GetBuffer());
*/
    TCHAR pFileTo[MAX_PATH * 2] = {0};
    TCHAR pFileFrom[MAX_PATH * 2] = {0};

    lstrcpy(pFileFrom, pFrom);
    lstrcpy(pFileTo, pTo);

	SHFILEOPSTRUCT FileOp = {0};

	// FileOp.hwnd = GetSafeHwnd();
	FileOp.fFlags = FOF_NOCONFIRMATION    //不出现确认对话框
	 				|FOF_NOCONFIRMMKDIR;  //需要时直接创建一个文件夹,不需用户确定
	FileOp.pFrom = pFileFrom;
	FileOp.pTo = pFileTo;
	FileOp.wFunc = FO_MOVE;

	return (SHFileOperation(&FileOp) == 0); 
}

// 重命名文件或文件夹
BOOL SHReNameFile(TCHAR *pTo, TCHAR *pFrom)
{
/*
BOOL SHDeleteFile(CString strPathTo, CString strPathFrom)
{
	LPCTSTR pTo = LPCTSTR(strPathTo.GetBuffer());
	LPCTSTR pFrom = LPCTSTR(strPathFrom.GetBuffer());
*/
    TCHAR pFileTo[MAX_PATH * 2] = {0};
    TCHAR pFileFrom[MAX_PATH * 2] = {0};

    lstrcpy(pFileFrom, pFrom);
    lstrcpy(pFileTo, pTo);

	SHFILEOPSTRUCT FileOp = {0};

	// FileOp.hwnd = GetSafeHwnd();
	FileOp.fFlags = FOF_NOCONFIRMATION;   //不出现确认对话框
	FileOp.pFrom = pFileFrom;
	FileOp.pTo = pFileTo;
	FileOp.wFunc = FO_RENAME;  
	   
	return SHFileOperation(&FileOp)==0;
 
}

///
// 文件夹:
// 1.检测文件夹是否存在
// 2.创建文件夹
// 3.检测文件夹操作状态
// 4.获取系统文件夹路径(如我的电脑、我的文档等)

// 1.检测文件夹是否存在
BOOL DirectoryExists(LPCTSTR lpszFileName)
{  
    DWORD dwAttributes = GetFileAttributes(lpszFileName);  
    if(dwAttributes == 0xFFFFFFFF)  
    {  
        return FALSE;  
    }   

    if((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)  
    {  
        return TRUE;  
    }  
    else  
    {  
        return FALSE;  
    }  
}  

// 2.创建文件夹
// CreateDirectory创建文件夹时,父文件夹必须存在,否则失败
// MakeSureDirectoryPathExists可以创建多级文件夹,但是不支持Unicode
// SHCreateDirectoryEx也可以创建多级文件夹,支持Unicode,支持XP SP2以上,Windows Server 2003以上

// SHCreateDirectoryEx
#include "shlobj.h"
#pragma comment(lib, "shell32.lib")

// strPath最后不包含'\'
BOOL DoCreateDirectory(CString strPath)
{
	BOOL ret = FALSE;
	ret = SHCreateDirectoryEx(NULL, strPath.GetBuffer(), NULL);
	// ret = SHCreateDirectoryEx(NULL, LPCTSTR(strPath), NULL);

	if (ret == ERROR_SUCCESS)
	{
		return TRUE;
	}

	return FALSE;
}

// CreateDirectory(未验证)
BOOL MyCreateDirectory(CString &szFileName)  
{  
    int nIndex = 1;  
    CString szTemp = szFileName;  
    do   
    {  
        if ( DirectoryExists(szTemp) )  
        {  
            szTemp.Format(_T("%s(%d)"), szFileName, nIndex++);  
            continue;  
        }  
#ifdef _WIN32_WCE  
        // 根目录创建时不要加'/'  
        if ( szTemp.ReverseFind(_T('//')) == 0 )  
        {  
            szTemp = szTemp.Mid(1);  
        }  
#endif  
        szFileName = szTemp;  
        return ( ::CreateDirectory(szFileName, NULL) > 0 );  
  
    } while ( nIndex < 1000 );  
  
    return FALSE;  
} 

// 3.检测文件夹操作状态(未验证)
BOOL InspectDirectoryPopedom( const CString szPath, DWORD dwFileAccess/* =GENERIC_READ|GENERIC_WRITE */ )  
{  
#ifdef _WINDOWS_  
    // wince下不支持  
    HANDLE hDir=CreateFile(szPath, dwFileAccess, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,   
           NULL, OPEN_EXISTING,  FILE_FLAG_BACKUP_SEMANTICS, NULL );  
    if ( hDir==INVALID_HANDLE_VALUE )  
    {  
        return false;  
    }  
    CloseHandle(hDir);  
#endif  
    return true;  
} 

// 4.获取系统文件夹路径(如我的电脑、我的文档等)(未完成)
CString GetSystemPath(int nAttribute /* =CSIDL_DESKTOP */)
{  
    CString csSystemPath = _T("");  
    TCHAR szPath[MAX_PATH + 1] = _T("");  
 
#ifdef  _WIN32_WCE  
    LPITEMIDLIST ppidl = NULL;  
#else  
    LPITEMIDLIST ppidl = NULL;  
#endif  

    if (SHGetSpecialFolderLocation(NULL, nAttribute, &ppidl) == S_OK)   
    {  
        if (SHGetPathFromIDList(ppidl, szPath))  
        {  
            csSystemPath = szPath;  
        }  
    }  
    return csSystemPath;  
}  

int GetSystemPath(CString &SysPath, int nAttribute /* = CSIDL_DESKTOP */)
{
    TCHAR szPath[MAX_PATH];
    BOOL ret = SHGetSpecialFolderPath(NULL, szPath, nAttribute, FALSE);
    
    SysPath.Format(_T("%s"), szPath);
    
    return ret;
}

int GetSystemPath(CString &SysPath, int nAttribute /* = CSIDL_DESKTOP */)
{
    TCHAR szPath[MAX_PATH];

    if (SUCCEEDED(SHGetFolderPath(NULL, nAttribute, NULL, 0, szPath)))
    {
        SysPath.Format(_T("%s"), szPath);

        return TRUE;
    }

    return FALSE;
}

// SHGetFolderPath示例
// TCHAR szPath[MAX_PATH];
// if(SUCCEEDED(SHGetFolderPath(NULL,
//                              CSIDL_PERSONAL|CSIDL_FLAG_CREATE,
//                              NULL,
//                              0,
//                              szPath)))
// {
//     PathAppend(szPath, TEXT("New Doc.txt"));
//     HANDLE hFile = CreateFile(szPath, );
// }

///

///
// 文件:
// 1.检测文件是否存在
// 2.检测文件名是否符合要求

// 1.检测文件是否存在
BOOL FileExists(LPCTSTR lpszFileName)  
{  
/*
BOOL FileExists(CString strFileName)  
{
	LPCTSTR lpszFileName = LPCTSTR(strFileName.GetBuffer());
*/
    DWORD dwAttributes = GetFileAttributes(lpszFileName);  
    if(dwAttributes == 0xFFFFFFFF)  
    {  
        return FALSE;  
    }   
  
    return TRUE;  
}  

// 2.检测文件名是否符合要求(未完成)
BOOL InspectFileNameRule(const CString &csFileName)  
{  
    // 文件名禁用字符列表  
    TCHAR szFILERULE[]= { '//', '/', ':', '*', '?', '/"', '<', '>', '|', '/0'};  
  
    for( DWORD i=0; i<STRLEN(szFILERULE); i++ )  
    {  
        if ( csFileName.Find( szFILERULE[i])>=0 )  
        {  
            return false;  
        }  
    }  
    return true;  
}  


///


/
// 使用FileOperation.h库
// 即使用SHFileOperation和SHCreateDirectory函数进行操作

#include "FileOperation.h"

// 复制文件对象到指定路径(可复制文件/文件夹到指定路径)
// strPathFrom、strPathTo均可为文件名或文件夹路径名
// 暂时只支持strPathTo为文件夹路径名
int CopyFileObject(CString strPathFrom, CString strPathTo)
{
    if ((strPathFrom.GetLength() <= 0) || (strPathTo.GetLength() <= 0))
    {
        return FALSE;
    }

    ///
    // 初始化
    CString szPathFrom = strPathFrom;
    CString szPathTo   = strPathTo;

    if (szPathFrom.Right(1) == '\\')
    {
        szPathFrom = strPathFrom.Left(strPathFrom.GetLength() - 1);
    }

    if (szPathTo.Right(1) == '\\')
    {
        szPathTo = strPathTo.Left(strPathTo.GetLength() - 1);
    }

    ///
    // 异常判断
    // 如果源文件对象与目的文件对象相同,不执行复制操作
    if (szPathFrom.Compare(szPathTo) == 0)
    {
        return FALSE;
    }

    // 检测源路径文件对象是否存在
    if (!FileExists(LPCTSTR(szPathFrom.GetBuffer())))
    {
        return FALSE;
    }

    // 如果目标路径文件夹不存在,则新建;否则删除目标文件夹后新建
    if (!DirectoryExists(LPCTSTR(szPathTo.GetBuffer())))
    {
        if (!DoCreateDirectory(szPathTo))
        {
            return FALSE;
        }
    }
    /*else
    {
        if (!SHDeleteFile(szPathTo.GetBuffer()))
        {
            return FALSE;
        }

        if (!DoCreateDirectory(szPathTo.GetBuffer()))
        {
            return FALSE;
        }
    }*/

    ///
    // 文件对象复制处理
    if (!SHCopyFile(szPathFrom.GetBuffer(), szPathTo.GetBuffer()))
    {
        return FALSE;
    }

    return TRUE;
}




API功能详解: 使用API函数SHFileOperation,这个函数可以同时拷贝、删除、改名或移动多个文件,甚至整个目录。如果你愿意,还可以显示相应的动画对话框,功能十分强大。SHFileOperation的参数是一个SHFILEOPSSTRUCT结构。这个结构中各成员的含义如下: - hwnd - 显示文件操作对话框的窗口句柄 - wFunc - 表示要进行的操作,可以取以下值: - FO_COPY - 拷贝文件。所要拷贝的文件由pFrom成员指定,目的地址有pTo成员指定。 - FO_DELETE - 删除pFrom指定的文件。(pTo 被忽略。) - FO_MOVE - 移动文件。所要移动的文件由pFrom成员指定,目的地址有pTo成员指定。 - FO_RENAME - 改名pFrom指定的文件。 - pFrom - 指定文件名的缓冲区的地址。必须以Chr(0)结尾。如果包括多个文件以Chr(0)分割。 - pTo - 指定目的文件名或目录的缓冲区的地址。必须以Chr(0)结尾。如果使用了FOF_MULTIDESTFILES标志,可以包括多个文件名,文件名之间以Chr(0)分割。 - fFlags - 标志: - FOF_ALLOWUNDO - 允许恢复 - FOF_FILESONLY - 如果使用了*.*,只操作文件。 - FOF_MULTIDESTFILES - pTo成员可以为多个目的文件。 - FOF_NOCONFIRMATION - 不显示确认对话框。 - FOF_NOCONFIRMMKDIR - 不确认是否建立目录。 - FOF_NOERRORUI - 如果有错误,不显示用户界面。 - FOF_RENAMEONCOLLISION - 如果目的文件已经存在,给要处理的文件一个新名字。 - FOF_SILENT - 不显示进度对话框。 - FOF_SIMPLEPROGRESS - 显示进度框,但不显示文件名。 - fAnyOperationsAborted -如果用户退出,该成员为TRUE,否则为FALSE。 - lpszProgressTitle - 进度框的标题,只有选择了FOF_SIMPLEPROGRESS标志才有效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值