一、问题的提出
Windows中文件夹的拷贝实现了单个文件到多级目录的拷贝,一般在处理大量数据拷贝之类耗时的操作,都会另外创建新的线程来处理。现在要编写一个多线程拷贝多级目录的程序,要求用多线程实现,在拷贝过程中程序界面响应其它消息,并且要求有拷贝的进度显示和状态显示。
二、拷贝多级目录的一些基本知识
MFC或WIN32 SDK没有提供拷贝目录的相关函数,或者不能显示拷贝的状态,如自定义的进度显示,所以只能通过自己遍历一个目录及子目录来获得,这就需要用到查找文件。MFC提供了CFindFile来实现这个功能。
对于拷贝函数,有CopyFile和CopyFileEx,CopyFileEx提供了进度显示等功能,但需要回调函数,比较麻烦且不符合程序的要求,所以用拷贝时的文件尺寸比来设置进度显示。
因为要在拷贝过程中响应用户,所以需要用到多线程,多线程实现并行处理,避免了某项任务长时间占用CPU时间,也不让用户感觉程序有“死掉”的感觉。
三、编程思路
创建一个基于对话框的程序,命名为CopyFolder
1、对于多线程处理
在程序的构造函数里,创建一个自动事件对象和一个线程,在线程回调函数里用循环等待事件信号,受信才会执行具体的拷贝工作。设置受信在开始拷贝函数中调用。另外程序提供了线程的挂起和恢复功能,线程的停止设置了标志位,以便使在循环拷贝中跳出循环,停止文件的拷贝。
2、得到目录
用
SHGetPathFromIDList和
BROWSEINFO处理来返回源文件夹和目标文件夹的路径
3、显示进度
进度的显示比是按源文件夹的总尺寸除当前正在拷贝的文件尺寸得到,但Windows没有提供相应得到文件夹尺寸的函数,根据使用Windows的经验,Windows也是通过递归循环得到尺寸,所以通过遍历每个文件得到尺寸并累加来得到所选文件夹的总尺寸。
4、同步界面
按是否正在拷贝来同步界面上所有的相关控件
5、拷贝文件夹
主要实现函数。
1)如何得到源文件相应的目标路径
递归查找得到源文件的路径,问题是目标路径的获得和设置。如源文件夹为G:/Documents/Article,目标路径选择为H:/,那么目标拷贝路径应该为H:/Article,对于拷贝源文件G:/Documents/Article/One/Sample.txt来说,目标路径应该为H:/Article/One/Sample.txt。如何从源文件路径中取得正确路径拷贝到目标路径,思路为得到当前源文件路径的长度(G:/Documents/Article/One/Sample.txt),减去一开始选择的路径(G:/Documents/Article),这样得到的是/One/Sample.txt,在加在拷贝路径的后面,形成H:/Article/One/Sample.txt。
2)如何创建目录
得到了源文件和目标文件的路径,但这样调用CopyFile并不能成功。因为可能Article或One并未创建,所以需要通过目标路径逐层创建目录。
具体实现为
int nPos = -1;
while( (nPos = strDest.Find( _T("//"), nPos+1) ) != -1 )
{
CString str = strDest.Left(nPos);
CreateDirectory(strDest.Left(nPos), NULL);
}
四、详见代码