mFC下文件的递归删除和拷贝

MFC 中 删除一个非空文件夹 (MFC 文件操作 一)
分类: C/C++ 程序开发 1107人阅读 评论(1) 收藏 举报

      最近在看MFC 的文件操作,从网上淘了一本比较讲MFC文件操作比较全的电子书,然后开始试手。在删除文件夹时,遇到了问题,通过查看MSDN和网友的论坛留言,自己总算是解决了这个问题,现在与大家共享。

 

      MFC中提供了删除文件夹的一个封装函数 RemoveDirectory(LPCTSTR lpPathName),我们只要把要删除的文件夹的路径传进去就可以删除了,貌似一切如此简单。我象征性的建立一个文件夹,然后在程序中删除了它,呵呵,一下就成功了。正当我要转手去做另外的操作时,我喜欢乱尝试的毛病就鬼使神差的让我做了这么一件事,在这个文件夹下我添加了几个新的子文件夹以及一些文件,这下我再试我的程序时就出现问题了,删不掉了!!

 

      原来-------RemoveDirectory(LPCTSTR lpPathName)欺骗了我,他只能删除空的文件夹,这下我有问题了,怎么才能删除一个文件夹,即便其中含有无数的子文件和子文件夹呢?

 

     RemoveDirectory(LPCTSTR lpPathName) 的这种行为其实是情有可原的,它为我们的操作提供了一种安全级别的控制。

     但我现在就想删除非空文件夹 , 怎么办呢????

 

 

     递归删除!!

 

     看到论坛上有人提出这一思想,我感觉很有道理,于是就基于这一思想,着手实现它!

 

     首先将文件夹下所有内容删除,再调用RemoveDirectory(LPCTSTR lpPathName)不就可以实现了么!!

 

     为此我专门写了一个函数来递归删除一个文件夹下的所有内容!

 

     请看我的代码

 

  1. void myDeleteDirectory(CString directory_path)   //删除一个文件夹下的所有内容   
  2. {     
  3.     CFileFind finder;  
  4.     CString path;  
  5.     path.Format("%s/*.*",directory_path);  
  6.     BOOL bWorking = finder.FindFile(path);  
  7.     while(bWorking){  
  8.         bWorking = finder.FindNextFile();  
  9.         if(finder.IsDirectory() && !finder.IsDots()){//处理文件夹   
  10.             myDeleteDirectory(finder.GetFilePath()); //递归删除文件夹   
  11.             RemoveDirectory(finder.GetFilePath());  
  12.         }  
  13.         else{//处理文件   
  14.             DeleteFile(finder.GetFilePath());  
  15.         }  
  16.     }  
  17. }  

 

     定义一个 CFileFind 类对象 来找文件夹下的所有子文件和子文件夹,然后依次判断它是 文件 还是 文件夹,

     如果是文件 就直接删除了,如果是文件夹就递归调用 该 myDeleteDirectory()函数,来删除其内容。然后在调用RemoveDirectory()来删除这个文件夹,这样不就好了么?

 

      为了测试我的程序是否是正确的,我创建了一个文件夹 ForVcTest,在其中添加了许多的子文件和文件夹,又在子文件夹中添加了文件和文件夹。写了这么一段测试程序,诸位请看:

 

  1. void DeleteAllDirectory() //删除文件夹  包括非空的文件夹   
  2. {  
  3.     //第一步 删除 该文件夹下所有文件   
  4.       myDeleteDirectory("C:/ForVcTest");  
  5.       
  6.     //第二步 删除该空文件夹   
  7.      RemoveDirectory("C:/ForVcTest");  
  8. }  

 

     测试结果出来了,我眼看着一个内容丰富的文件夹,就在我的程序运行后消失了!真是很舒心啊!呵呵!

 

 

上一篇博文中已经提到了CFileFind类,并且用它实现了删除任意文件夹,此处不再对其赘述。

 

      在实现文件复制过程时,一个问题i是我纠结了许久,CFileFind 类的成员函数 GetFilePath()与GetFileName(),其实很好理解的两个函数,一个是获得文件的路径,一个是获得文件的名字。但我却在理解上犯了一个错误,就是文件路径究竟包不包含文件名字,如有文件C:/Test/1.txt ,那么它的路径和名称分别是什么?我理解成了,路径:C:/Test 名称1.txt ,我按照我的理解编写这个复制功能的实现代码,老师出错,最后我才发现,原来 路径是包含文件名称的 ,即上面的文件 路径即是:C:/Test/1.txt。

 

      似乎是个很低级的错误,但是的确困扰了我一段时间。

 

      回到正题。

 

     具体的实现思想类似于上一篇博文“MFC 中 删除一个非空文件夹”

 

    请看源代码: 

  1. void myCopyDirectory(CString source, CString target)  
  2. {  
  3.     CreateDirectory(target,NULL); //创建目标文件夹   
  4.     //AfxMessageBox("创建文件夹"+target);   
  5.     CFileFind finder;  
  6.     CString path;  
  7.         path.Format("%s/*.*",source);  
  8.     AfxMessageBox(path);  
  9.     bool bWorking = finder.FindFile(path);  
  10.     while(bWorking){  
  11.         bWorking = finder.FindNextFile();  
  12.         AfxMessageBox(finder.GetFileName());  
  13.         if(finder.IsDirectory() && !finder.IsDots()){ //是文件夹 而且 名称不含 . 或 ..   
  14.             myCopyDirectory(finder.GetFilePath(),target+"/"+finder.GetFileName()); //递归创建文件夹+"/"+finder.GetFileName()   
  15.         }  
  16.         else//是文件 则直接复制   
  17.             //AfxMessageBox("复制文件"+finder.GetFilePath());//+finder.GetFileName()   
  18.             CopyFile(finder.GetFilePath(),target+"/"+finder.GetFileName(),FALSE);  
  19.         }  
  20.     }  
  21. }  

 

   

    源代码不是很难理解,不再详解

 

 

一、 从路径中 提取扩展名

 

 

[c-sharp] view plain copy print ?
  1. CString path("C:/ForVcTest/diary.txt");  
  2. CString ext = path.Mid(path.ReverseFind('.')+1);  
  3. AfxMessageBox(ext);  

 

解析:1. CString::Mid

             CString Mid(int nFirst) const;

             CString Mid(int nFirst,int nCount) const;

             nCount代表要提取的字符数,nFirst代表要提取的开始位置

      

         2. CString::CString::ReverseFind

             int ReverseFind( TCHAR ch ) const;

             返回值

                   返回此CString 对象中与要求的字符匹配的最后一个字符的索引;如果没有找 到需要的字符则返回-1。

             参数

                    ch 要搜索的字符

       

         3. 从文件路径中找到 ' . '的位置,然后索引后移一个即是后缀名的起始字符的索引

             利用Mid函数提取出 后缀名

 

二、从路径中 提取文件名

 

[c-sharp] view plain copy print ?
  1. CString path("C:/ForVcTest/diary.txt");  
  2. CString name = path.Mid(path.ReverseFind('/')+1);  
  3. AfxMessageBox(name);  

 

 

三、获取文件属性

 

[c-sharp] view plain copy print ?
  1. DWORD dwAttr = GetFileAttributes("C:/ForVcTest/2.txt");//获取文件的属性   
  2. if (dwAttr == FILE_ATTRIBUTE_ARCHIVE){  
  3.     AfxMessageBox("FILE_ATTRIBUTE_ARCHIVE");  
  4. }  

 

四、设置文件属性

 

[c-sharp] view plain copy print ?
  1. SetFileAttributes("C:/ForVcTest/2.txt",FILE_ATTRIBUTE_READONLY);//|FILE_ATTRIBUTE_HIDDEN  

 

五、获取当前程序所在路径

 

  1. //提取文件路径   
  2. char appName[_MAX_PATH];  
  3. GetModuleFileName(NULL,appName,_MAX_PATH);  
  4. CString szPath(appName);  
  5. AfxMessageBox(szPath);  

  

 

解析:DWORD WINAPI GetModuleFileName(
                        __in_opt HMODULE hModule,
                        __out LPTSTR lpFilename,
                        __in DWORD nSize);

 

        返回包含指定模块的文件的全路径,这个模块必须是已经被当前进程加载的。

 

六、移动文件

 

[c-sharp] view plain copy print ?
  1. MoveFile("C:/ForVcTest/diary.txt","C:/ForVcTest/newCopy.txt");  

 

移动后 源文件被删除,目标文件被创建

 

七、Path Name Title 的区别

 

[c-sharp] view plain copy print ?
  1. CFile file("C:/ForVcTest/newCopy.txt",CFile::modeRead);  
  2.   
  3. CString szPath = file.GetFilePath();  
  4. CString szName = file.GetFileName();  
  5. CString szTitle = file.GetFileTitle();  
  6.   
  7. AfxMessageBox("szPath = "+szPath);  
  8. AfxMessageBox("szName = "+szName);  
  9. AfxMessageBox("szTitle = "+szTitle);  

 

我写了上面一段测试程序,得到的结果是

szPath = "C:/ForVcTest/newCopy.txt"

szName = "newCopy.txt"

szTitle = "newCopy.txt"

 

MSDN 里面说 title 是 newCopy  但是我的运行结果和它讲的不一样。

 

这里我就不是很明白了,这后两个概念到底有什么区别?

 

我又研究了一番,终于发现了他们的区别。

 

如果将文件的后缀名 隐藏以来,你就发现,name = newCopy.txt  而 title = newCopy

 

这就是区别吧。

 

 

希望看这篇文章的博友能和我一起交流讨论这个问题。

 

八、文件分隔

 

[c-sharp] view plain copy print ?
  1. bool SplitFile()   
  2. {  
  3.     //文件分割   
  4.     CFile m_File;  
  5.     CString m_FileName,m_FileTitle,m_FilePath;  
  6.     m_FilePath = "C://ForVcTest//newCopy.txt";  
  7.     char pBuf[40];  
  8.     if(m_File.Open(m_FilePath,CFile::modeRead | CFile::shareDenyWrite))  
  9.     {  
  10.         m_FileName=m_File.GetFileName();  
  11.         m_FileTitle=m_File.GetFileTitle();  
  12. //      DWORD FileLength=m_File.GetLength();   
  13. //      DWORD PartLength=FileLength/2+FileLength%2;   
  14.         int nCount=1;  
  15.         CString strName;  
  16.         CFile wrFile;  
  17.         DWORD ReadBytes;  
  18.         while(true)  
  19.         {  
  20.             ReadBytes=m_File.Read(pBuf,40);   //ReadBytes 实际读取的字节数   
  21.             strName.Format("C://ForVcTest//%s%d.txt",m_FileTitle,nCount);  
  22.             wrFile.Open(strName,CFile::modeWrite | CFile::modeCreate);  
  23.             wrFile.Write(pBuf,ReadBytes);  
  24.             wrFile.Close();  
  25.             if(ReadBytes<40) //实际读取的字节数 不足 分配的大小,则说明文件读完了   
  26.                 break;  
  27.             nCount++;  
  28.         }  
  29.         m_File.Close();  
  30.     }  
  31.     else{  
  32.         AfxMessageBox("不能打开文件");  
  33.                   return fasle;  
  34.           }  
  35.          return true;  
  36. }  

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值