VC 复制移动删除重命名文件文件夹

时间:2022-09-24 12:26:55
文件操作 复制移动删除重命名文件文件夹


━━━━━━━━━━━━━━━━━━━━━━━━

说明:
1.以下封装了4个函数_CopyFile,_DeleteFile,_MoveFile,_ReNameFile
2.每个函数都先拷贝了原来的路径,保证了路径是以2个/0/0结尾。(如果不以2个/0/0结尾,往往会出错)
3.对于文件或文件夹都适用

 

/*
能产生对话框的标志:
FOF_SILENT             //progress dialog           
FOF_RENAMEONCOLLISION  //replace dialog
FOF_NOCONFIRMATION     //confirmation dialog
FOF_NOCONFIRMMKDIR     //asks for your permission to create a new folder
FOF_NOERRORUI          //error message

FOF_ALLOWUNDO             //允许放回回收站,一般这个最好做默认
FOF_NOCONFIRMATION        //不出现确认对话框(当需要覆盖时)
FOF_SILENT                //不显示进度对话框
FOF_NOERRORUI            //No user interface will be displayed if an error occurs.
FOF_NOCONFIRMMKDIR        //如果目的目录不存在,就默认创建,不需确认
FOF_RENAMEONCOLLISION    //如果文件(夹)已存在,自动为其添加序列号修改文件名。此时不会出现确认对话框
FOF_MULTIDESTFILES         //把文件夹里的所有内容复制到FileOp.pTo指定的文件夹里,而不是直接复制一个文件夹
FOF_SIMPLEPROGRESS        //Displays a progress dialog box but does not show the file names
FOF_CONFIRMMOUSE        //Not currently implemented.
FOF_FILESONLY:            //执行通配符,只执行文件;
FOF_WANTMAPPINGHANDLE:    //要求SHFileOperation()函数返回正处于操作状态的实际文件列表,文件列表
名柄保存在hNameMappings成员中。SHFILEOPSTRUCT结构还包含一个SHNAMEMAPPING结构的数组,此数组
保存由SHELL计算的每个处于操作状态的文件的新旧路径。


说明:
1.以下封装了4个函数_CopyFile,_DeleteFile,_MoveFile,_ReNameFile
2.每个函数都先拷贝了原来的路径,保证了路径是以2个/0/0结尾。(如果不以2个/0/0结尾,往往会出错)
3.对于文件或文件夹都适用
*/


/****************************************************************************
复制文件或者文件夹,需要把路径添加2个/0/0
****************************************************************************/
static
bool _CopyFile(const TCHAR *_pFrom,const TCHAR *_pTo,WORD flags=FOF_NOCONFIRMATION)
{
    TCHAR pTo[MAX_PATH]={0};    _tcscpy(pTo,_pTo);
    TCHAR pFrom[MAX_PATH]={0};    _tcscpy(pFrom,_pFrom);

    SHFILEOPSTRUCT FileOp={0};
    FileOp.fFlags=    flags;
    FileOp.pFrom =    pFrom;
    FileOp.pTo     =    pTo;
    FileOp.wFunc =    FO_COPY;
    return SHFileOperation(&FileOp) == 0;    
}

/****************************************************************************
删除文件或者文件夹,需要把路径添加2个/0/0
****************************************************************************/
static
bool _DeleteFile(const TCHAR* _pFrom,WORD flags=FOF_ALLOWUNDO|FOF_NOCONFIRMATION)
{
    TCHAR pFrom[MAX_PATH]={0};    _tcscpy(pFrom,_pFrom);

    SHFILEOPSTRUCT FileOp={0};
    FileOp.pFrom =    pFrom;
    FileOp.pTo     =    NULL;                //一定要是NULL
    FileOp.fFlags=    flags;
    FileOp.wFunc =    FO_DELETE;            //删除操作
    return SHFileOperation(&FileOp) == 0;
}

/****************************************************************************
移动文件或者文件夹,需要把路径添加2个/0/0
****************************************************************************/
static
bool _MoveFile(const TCHAR *_pFrom,const TCHAR *_pTo,WORD flags=FOF_NOCONFIRMATION)
{
    TCHAR pTo[MAX_PATH]={0};    _tcscpy(pTo,_pTo);
    TCHAR pFrom[MAX_PATH]={0};    _tcscpy(pFrom,_pFrom);

    SHFILEOPSTRUCT FileOp={0};
    FileOp.fFlags=    flags;
    FileOp.pFrom =    pFrom;
    FileOp.pTo     =    pTo;
    FileOp.wFunc =    FO_MOVE;
    return SHFileOperation(&FileOp) == 0;    
}

/****************************************************************************
重命名文件或者文件夹
可以的话用 rename(buf,TempFilePath) (文件和文件夹都可以) because不需要把路径添加2个/0/0
****************************************************************************/
static
bool _ReNameFile(const TCHAR *_pFrom,const TCHAR *_pTo,WORD flags=FOF_NOCONFIRMATION)
{
    TCHAR pTo[MAX_PATH]={0};    _tcscpy(pTo,_pTo);
    TCHAR pFrom[MAX_PATH]={0};    _tcscpy(pFrom,_pFrom);

    SHFILEOPSTRUCT FileOp={0};
    FileOp.fFlags = flags;
    FileOp.pFrom =    pFrom;
    FileOp.pTo     =    pTo;
    FileOp.wFunc =    FO_RENAME;
    return SHFileOperation(&FileOp) == 0;    
}



调用示例:

void CDemoDlg::OnButton1()
{
    bool rel=_CopyFile(_T("c://t.bmp"),_T("C://pic_1.bmp") );
    traceRel(rel,_T("_CopyFile"));
}

void CDemoDlg::OnButton2()
{
    bool rel=_CopyFile(_T("c://t.bmp"),_T("C://pic_1.bmp"),FOF_SILENT);
    traceRel(rel,_T("_CopyFile"));
}

void CDemoDlg::OnButton3()
{
    //复制文件夹并且重命名,需要FOF_MULTIDESTFILES
    //当覆盖时如果里面有的文件不会被删除
    bool rel=_CopyFile(_T("c://a"),_T("C://d"),FOF_MULTIDESTFILES|FOF_NOCONFIRMATION);
    traceRel(rel,_T("_CopyFile"));
}

void CDemoDlg::OnButton4()
{
    //复制文件到指定目录下,不需要 FOF_MULTIDESTFILES,pTo目录要有效,否则虽能复制,但结果怪怪的    
    bool rel=_CopyFile(_T("c://a"),_T("C://d"),FOF_NOCONFIRMATION);
    traceRel(rel,_T("_CopyFile"));
}


void CDemoDlg::OnButton5()
{
    bool rel=_DeleteFile(_T("C://d"),FOF_ALLOWUNDO|FOF_NOCONFIRMATION/*|FOF_SILENT*/);
    traceRel(rel,_T("_DeleteFile"));
}


void CDemoDlg::OnButton6()
{
    bool rel=_MoveFile(_T("c://t.bmp"),_T("d://erw.bmp"),FOF_NOCONFIRMATION|FOF_SILENT);
    traceRel(rel,_T("_CopyFile"));
}


void CDemoDlg::OnButton7()
{
    bool rel=_ReNameFile(_T("c://t.bmp"),_T("c://v.bmp"),FOF_NOCONFIRMATION|FOF_SILENT);
    traceRel(rel,_T("_ReNameFile"));
}

void CDemoDlg::OnButton8()
{
    bool rel=_ReNameFile(_T("c://a"),_T("c://b"),FOF_NOCONFIRMATION|FOF_SILENT);
    traceRel(rel,_T("_ReNameFile"));
}



━━━━━━━━━━━━━━━━━━━━━━━━

以下来自网络:


参数详解:

Typedef struct _ShFILEOPSTRUCT
{
HWND hWnd; //消息发送的窗口句柄;
UINT wFunc; //操作类型
LPCSTR pFrom; //源文件及路径
LPCSTR pTo; //目标文件及路径
FILEOP_FLAGS fFlags; //操作与确认标志
BOOL fAnyOperationsAborted; //操作选择位
LPVOID hNameMappings; //文件映射
LPCSTR lpszProgressTitle; //文件操作进度窗口标题
}SHFILEOPSTRUCT, FAR * LPSHFILEOPSTRUCT;

  在这个结构中,hWnd是指向发送消息的窗口句柄,pFrom与pTo是进行文件操作的源文件名和目标文件名,它包含文件的路径,对应单个文件的路径字符串,或对于多个文件,必须以NULL作为字符串的结尾或文件路径名之间的间隔,否则在程序运行的时候会发生错误。另外,pFrom和pTo都支持通配符 *和?,这大大方便了开发人员的使用。例如,源文件或目录有两个,则应是:char pFrom[]="d://Test1/0d://Text.txt/0",它表示对要D:盘Test目录下的所有文件和D:盘上的Text.txt文件进行操作。字符串中的"//"是C语言中的'/'的转义符,'/0'则是NULL。wFunc 是结构中的一个非常重要的成员,它代表着函数将要进行的操作类型,它的取值为如下:

  FO_COPY: 拷贝文件pFrom到pTo 的指定位置。
  FO_RENAME: 将pFrom的文件名更名为pTo的文件名。
  FO_MOVE: 将pFrom的文件移动到pTo的地方。
  FO_DELETE: 删除pFrom指定的文件。

  使用该函数进行文件拷贝、移动或删除时,如果需要的时间很长,则程序会自动在进行的过程中出现一个无模式的对话框(Windows操作系统提供的文件操作对话框),用来显示执行的进度和执行的时间,以及正在拷贝、移动或删除的文件名,此时结构中的成员lpszProgressTitle显示此对话框的标题。fFlags是在进行文件操作时的过程和状态控制标识。它主要有如下一些标识,也可以是其组合:

FOF_ALLOWUNDO             //允许放回回收站,一般这个最好做默认
FOF_NOCONFIRMATION        //不出现确认对话框(当需要覆盖时)
FOF_SILENT                //不显示进度对话框
FOF_NOERRORUI            //No user interface will be displayed if an error occurs.
FOF_NOCONFIRMMKDIR        //如果目的目录不存在,就默认创建,不需确认
FOF_RENAMEONCOLLISION    //如果文件(夹)已存在,自动为其添加序列号修改文件名。此时不会出现确认对话框
FOF_MULTIDESTFILES         //把文件夹里的所有内容复制到FileOp.pTo指定的文件夹里,而不是直接复制一个文件夹
FOF_SIMPLEPROGRESS        //Displays a progress dialog box but does not show the file names
FOF_CONFIRMMOUSE        //Not currently implemented.
FOF_FILESONLY:            //执行通配符,只执行文件;
FOF_WANTMAPPINGHANDLE:    //要求SHFileOperation()函数返回正处于操作状态的实际文件列表,文件列表
名柄保存在hNameMappings成员中。SHFILEOPSTRUCT结构还包含一个SHNAMEMAPPING结构的数组,此数组
保存由SHELL计算的每个处于操作状态的文件的新旧路径。


转自http://blog.csdn.net/jhb92/archive/2007/04/13/1563452.aspx

Shell的文件操作函数
SHFileOperation
功能:
1.复制一个或多个文件
2.删除一个或多个
3.重命名文件
4.移动一个或多个文件

有一样的Win32API功能函数是:
CopyFile(),DeleteFile(),MoveFile()
MoveFile可以对文件重命名!
Win32 API 的层次比SHFileOperation低

SHFileOperation
的重要参数
1.wFunc //对pFrom pTo要执行的操作
2.fFlags //影响对wFunx的操作
3.hNameMappings   //有系统填充,和你也可以填充
4.lpszProgressTitle

pFrom pTo 在结尾是两个'/0/0'
通常用一个'/0',这样会失败的!!
当FOF_MULTIDESTFILES
szPFrom[lstrlen(szPFrom)+1]=0

szPFrom:必须先确定他所指定的文件存在!
可以是单个文件名,*.*,或包含统配符的文件名
注意必须是文件名,不是文件所在的文件夹名
szSource:可以是一个目录,如果不是目录,但又有
多个文件,那么必须和szPFrom的每一个文件对应,还要指定
FOF_MULTIDETFILES标志


Source and Target
多个文件---> 一个文件夹
许多单独的文件---->一个文件夹
单独文件--->单独文件
许多单独的文件---->许多单独的文件

单独文件:知道名字的文件
多个文件:带有统配符的文件
注意到source中没有对文件夹的操作!!


!!!!
SHFileOperation能操作网络上的文件
如果你想将本地文件复制到192.168.1.99
那么只要在192.168.1.99上共享123目录
然后将pTo设置为//192.168.1.99/123
就可以了
但不要设置为//192.168.1.99


对hNameMappings操作是Undocumented!!
如果没有指定hNameMappings
那么hNameMappings一直是NULL
只有当某种操作(copy,move,rename)引起了文件名冲突了,hNameMappings才不是NULL!!!
当第一次copy某些文件到空目录中时hNameMappings一定是NULL
所以hNameMappings只是内存中的一块地区用来让Explorer.exe保存被重命名的文件,以避免文件名冲突!
上面知道了如何才能使hNameMappings有效
现在如何使用hNameMappings,及其所指的结构大小?并取得这个内存块的内容呢?
hNameMappings 是简单LPVOID无法使用loop
要使用hNameMappings,必须定义一个结构体
struct HANDLETOMAPPINGS {
    UINT              uNumberOfMappings; // number of mappings in array
    LPSHNAMEMAPPING   lpSHNameMapping;    // pointer to array of mappings
};
但是可以写一个Enumerate function to enumerate lpSHNameMapping指向的内存块,并且是让Window自己调用我的,不是我主动调用,象Loop


━━━━━━━━━━━━━━━━━━━━━━━━

另外2个删除文件夹的函数:


//删除文件夹目录(非空)

bool DeleteDirectory(char* sDirName)
{
    CFileFind tempFind;
    char sTempFileFind[200] ;
    
    sprintf(sTempFileFind,"%s*.*",sDirName);
    BOOL IsFinded = tempFind.FindFile(sTempFileFind);
    while (IsFinded)
    {
        IsFinded = tempFind.FindNextFile();
        
        if (!tempFind.IsDots())
        {
            char sFoundFileName[200];
            strcpy(sFoundFileName,tempFind.GetFileName().GetBuffer(200));
            
            if (tempFind.IsDirectory())
            {
                char sTempDir[200];
                sprintf(sTempDir,"%s/%s",sDirName,sFoundFileName);
                DeleteDirectory(sTempDir);
            }
            else
            {
                char sTempFileName[200];
                sprintf(sTempFileName,"%s/%s",sDirName,sFoundFileName);
                _DeleteFile(sTempFileName);
            }
        }
    }
    tempFind.Close();
    if(!RemoveDirectory(sDirName))
    {
        return FALSE;
    }
    return TRUE;
}


//下面是应用,CString m_strDir 是一个文件夹路径,如:d:downloadpic

BOOL DelAll()
{
    if(PathFileExists(m_strDir))     
        DeleteDirectory((LPSTR)(LPCTSTR)m_strDir);
    return 1;
}



// 删除文件夹及其所有内容
void RemoveFolder(const CString &strPathName)
{
    CString path = strPathName;
    if (path.Right(1) != _T("//"))
        path += _T("//");
    path += _T("*.*");
    
    CFileFind ff;
    BOOL res = ff.FindFile(path);
    while (res)
    {
        res = ff.FindNextFile();
        // 是文件时直接删除
        if (!ff.IsDots() && !ff.IsDirectory())
            DeleteFile(ff.GetFilePath());
        else if (ff.IsDots())
            continue;
        else if (ff.IsDirectory())
        {
            path = ff.GetFilePath();
            // 是目录时继续递归,删除该目录下的文件
            RemoveFolder(path);
            ::RemoveDirectory(path);
        }
    }
}



━━━━━━━━━━━━━━━━━━━━━━━━

推荐:

谈老师的BLOG (佛教大德)
狮姐的博客(狮子窝,学佛与灵魂之探究)
大方广(学习传统文化)
慈善点击(轻松一点,行善积德,何乐不为)
电影《地球公民》(揭示不为人知的一面)  
心向光明 远离邪淫(现世警钟,不可不看)
戒淫(上篇)(正淫节欲,戒除邪淫)
戒淫(中篇)(纵欲之乐,忧患随之)
公民教育——命由我造