今天本想写个类似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