最近工作中涉及到很多文件和文件夹的处理,包括删除、检测是否存在、移动、复制等,用过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;
}