今天本想写个类似FastCopy的文件快速复制工具,先把文件快速复制的原理搞清了..准备着手写时
却发现目录复制时要保持原目录结构却是个难题...想了想,用递归实现最简洁...
可是实现的时候却遇到了些难题....大家往下看
下面是递归实现遍历一个目录结构并复制的流程图:
流程看着很简单..可是实现上却很容易犯一些细节上的问题
最严重的就是堆栈问题
开始时我是把每次调用MyCopyFile的两个变量定义在了函数MyCopyFile中,也就是定义在了堆栈中
其实这也是大家用递归函数时正常的使用方法,可是在本例中却不实用.
如果是一个简单的目录,可能还好..可是如果一个目录下有很多很深的目录,
最后的错误就是XXXXX内存不可读的一个消息框弹出来
为什么呢..因为堆栈被那俩个变量填满了..最后堆栈中就分配不到内存了
所以最后我的想法是把这两个变量定义为全局变量,调用递归时将这两个变量修改成要压栈的变量
函数返回时再将它们修改回
大家看我代码中的函数EnterDirectory和函数LeaveDirectory就是起这个功能
下面是目录复制的一个简单代码,代码中并没有复制文件,只是把目录复制的过程打印出来了
大家可以下下去测试下:O(∩_∩)O
代码:
// CopyFileA.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <stdio.h> char szSrcName[256];//保存当前目录的名字(非路径) char szFindDir[256];//保存FindFirstFile的第一个参数 char src[256];//源路径 char dst[256];//目的路径 //判断是否是文件 BOOL IsFile(LPSTR lpFile) { DWORD dwFileAtt=GetFileAttributes(lpFile); if ((dwFileAtt&FILE_ATTRIBUTE_DIRECTORY)!=0) { return FALSE; } return TRUE; } //通过当前路径获取当前文件名 void GetSrcFileName(LPSTR src) { int n=lstrlen(src); for (;src[n-1]!='\\';n--) ; lstrcpy(szSrcName,src+n); } //进入目录 void EnterDirectory(LPSTR src,LPSTR file) { int n=lstrlen(src); if (src[n-1]=='\\') { memcpy(src+n,file,lstrlen(file)+1); } else { memcpy(src+n,"\\",1); memcpy(src+n+1,file,lstrlen(file)+1); } } //离开目录 void LeaveDirectory(LPSTR path) { int n=lstrlen(path)-1; for (;path[n]!='\\';n--) ; path[n]='\0'; } //初始化szFindDir变量 void InitFind(LPSTR src) { int n=lstrlen(src); if (src[n-1]=='\\') { memcpy(szFindDir,src,n); memcpy(szFindDir+n,"*",2); } else { memcpy(szFindDir,src,n); memcpy(szFindDir+n,"\\*",3); } } //复制的递归函数 void MyCopyFile() { if (IsFile(src)) { printf(src); printf("\n复制到\n"); printf(dst); printf("\n\n"); //具体的复制是在这里实现 //do LeaveDirectory(src); return; } else { InitFind(src); WIN32_FIND_DATA* lpWfd=new WIN32_FIND_DATA;//如果直接定义WIN32_FIND_DATA Wfd,当目录结构比较复杂,则程序运行到最后会出错,因为堆栈容易满 //则程序运行到最后会出错,因为堆栈容易满 HANDLE hFile=FindFirstFile(szFindDir,lpWfd); GetSrcFileName(src); EnterDirectory(dst,szSrcName); do { if ((lstrcmp(lpWfd->cFileName,".") & lstrcmp(lpWfd->cFileName,".."))!=0) { EnterDirectory(src,lpWfd->cFileName); MyCopyFile(); } } while(FindNextFile(hFile,lpWfd)); delete lpWfd; LeaveDirectory(dst); LeaveDirectory(src); } } //main int main(int argc, char* argv[]) { if (argc!=3) { printf("useage:\r\ncopyfilea src dst\n \ \rexample:\r\n \ \rcopyfilea c:\\ d:\\ 把c盘内容全部复制到d盘\r\n \ \rcopyfilea c:\\boot.ini d:\\dir 把c:\\boot.ini复制到存在的目录d:\\dir\r\n \ \rcopyfilea c:\\windows d:\\dir 把目录c:\\windows复制到d:\\dir目录中\r\n \ \r\t\t本程序只是示例,打印出复制过程中的目录结构"); getchar(); return 1; } lstrcpy(src,argv[1]); lstrcpy(dst,argv[2]); MyCopyFile(); return 0; } //by hatling //2009.8.8