[MFC]利用Win32 API遍历文件系统

原创 2015年07月09日 16:49:48

1. 遍历文件系统所需的工具:

    1) MFC的CFile并没有对遍历文件系统的功能进行面向对象包装,因此遍历文件系统必须使用较为原始、底层的Win32 API;

    2) 大致步骤是:

         i. 使用::SetCurrentDirectory函数设定当前处于什么目录下(Windows中叫做文件夹);

         ii. 使用::FindFirstFile获取当前文件夹下的第一个文件的“查找句柄”,注意!不是该文件的文件句柄,而是一种查找句柄,Win32使用了一种“查找结构”来支持文件的遍历;

         iii. 接着反复调用::FindNextFile获取下一个文件的“查找句柄”,其中可以判断该文件是否为文件夹,如果是文件夹的话还可以递归地进入该文件夹进行遍历;

    3) 在使用Find函数的时候会将查找的文件的相关信息填写到一个叫做“查找结构”的结构体中,然后可以利用该结构体中该文件的信息进行一些操作,该结构就是WIN32_FIND_DATA结构体:

struct WIN32_FIND_DATA {
	DWORD dwFileAttributes; // 文件属性,比如是文件还是文件夹等
	FILETIME ftCreationTime; // 文件创建时间
	FILETIME ftLastAccessTime; // 最近一次文件被访问的时间(包括读写)
	FILETIME ftLastWriteTime; // 最近一次文件被写的时间
	CHAR cFileName[MAX_PATH]; // 文件的完整绝对路径
	...
};
!要判断查找的文件是文件还是文件夹只需要看一下dwFileAttributes的位掩码FILE_ATTRIBUTE_DIRECTORY是否为1就行了

    4) FindFirstFile:

         i. HANDLE ::FindFirstFile(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData);

         ii. 第一个参数是目标文件名,可以使用通配符,一般在遍历的时候查找的第一个文件都用_T("*.*")来表示;

         iii. 第二个参数就是上面所说的WIN32_FIND_DATA结构的指针,查找到的文件的相关信息就保存在该结构体中;

         iv. 返回值就是相关的“查找句柄”,而不是文件句柄hFile,也不是WIN32_FIND_DATA的句柄,而是Win32 API内部维护的一个查找体的句柄,如果失败则返回INVALID_HANDLE_VALUE;

    5) FindNextFile:

         i. BOOL ::FindNextFile(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindData);

         ii. 第一个参数就是上一次查找得到的查找句柄,通常在调用FindFirstFile之后将返回值传给该参数进行迭代查找,查找的文件的信息同样放在lpFindData中;

         iii. 调用成功返回TRUE,否则返回FALSE;

    6) SetCurrentDirectory:

         i. BOOL ::SetCurrentDirectory(LPCTSTR lpPathName);

         ii. 将当前所在目录设成lpPathName所指定的目录,可以是绝对路径也可以是相对路径;

         iii. 有时可能提供的路径有问题,因此调用失败返回FALSE,成功则为TRUE;

    7) GetCurrentDirectory:获取当前路径

         i. BOOL ::GetCurrentDirectory(DWORD nBufferLength, LPSTR lpBuffer);

         ii. 第一个参数是缓冲区能接受的字符个数,注意!是字符个数而不是字节数,这最主要是兼容Unicode;

         iii. lpBuffer就是缓冲区;

         iv. 为了兼容Unicode最好这样调用:::GetCurrentDirectory(sizeof(szPath) / sizeof(TCHAR), szPath);


2. 示例——递归遍历一个文件夹:

void trace_t(int nCount) // 在一行的开头打nCount个制表符以示文件夹的层级
{
	while (nCount)
	{
		TRACE(_T("\t"));
		nCount--;
	}
}

void EnumerateFile(int nLevel) // 递归遍历文件系统
{
	WIN32_FIND_DATA fd;
	HANDLE hFind = ::FindFirstFile(_T("*.*"), &fd); // 开始从任意位置查找

	if (hFind != INVALID_HANDLE_VALUE) // 注意FindFirstFile的返回值是HANDLE
	{
		do 
		{
			if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				CString name = fd.cFileName;
				if (name != _T(".") && name != _T(".."))
				{
					trace_t(nLevel); // 先打印表示所在层级的制表符
					TRACE(_T("[D]%s\n"), fd.cFileName); // 文件夹用[D]来表示

					::SetCurrentDirectory(fd.cFileName); // 进入刚查找的文件夹
					EnumerateFile(nLevel + 1); // 如果是文件夹则递归往下遍历
					::SetCurrentDirectory(_T("..")); // 遍历完后返回上层文件夹中继续遍历
				}
			}
			else
			{
				CString name = fd.cFileName;
				trace_t(nLevel);
				TRACE(_T("[F]%s\n"), fd.cFileName); // 普通文件用[F]来表示
			}
		} while (::FindNextFile(hFind, &fd)); // 继续查找,注意FindNextFile返回值是BOOL
		::FindClose(hFind);
	}
}

void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
	::SetCurrentDirectory(_T("C:\\Proj")); // 设置遍历目标文件夹
	EnumerateFile(0); // 刚开始时层级是0,即第一层中的文件名前面没有制表符
}

结果如下:

[D]mfc
	[D]code
		[F].Hello.h.swp
		[F]Hello.cpp
		[F]Hello.h
	[D]p1
		[D]Hello
			[D]Debug
				[F]Hello.exe
				[F]Hello.ilk
				[F]Hello.obj
				[F]Hello.pch
				[F]Hello.pdb
				[F]vc60.idb
				[F]vc60.pdb
			[F]Hello.cpp
			[F]Hello.dsp
			[F]Hello.dsw
			[F]Hello.h
			[F]Hello.ncb
			[F]Hello.opt
			[F]Hello.plg
		[D]Shapes
			[F]ChildView.cpp
			[F]ChildView.h
			[D]Debug
			[F]MainFrm.cpp
			[F]MainFrm.h
			[F]ReadMe.txt
			[D]res
				[F]Shapes.ico
				[F]Shapes.rc2
			[F]Resource.h
			[F]Shapes.aps
			[F]Shapes.clw
			[F]Shapes.cpp
			[F]Shapes.dsp
			[F]Shapes.dsw
			[F]Shapes.h
			[F]Shapes.ncb
			[F]Shapes.opt
			[F]Shapes.rc
			[F]StdAfx.cpp
			[F]StdAfx.h
		[D]Test
			[D]Debug
				[F]Test.exe
				[F]Test.ilk
				[F]Test.obj
				[F]Test.pch
				[F]Test.pdb
				[F]vc60.idb
				[F]vc60.pdb
			[F]Test.cpp
			[F]Test.dsp
			[F]Test.dsw
			[F]Test.h
			[F]Test.ncb
			[F]Test.opt
			[F]Test.plg
		[D]TicTac
			[D]Debug
				[F]TicTac.exe
				[F]TicTac.ilk
				[F]TicTac.obj
				[F]TicTac.pch
				[F]TicTac.pdb
				[F]vc60.idb
				[F]vc60.pdb
			[F]TicTac.cpp
			[F]TicTac.dsp
			[F]TicTac.dsw
			[F]TicTac.h
			[F]TicTac.ncb
			[F]TicTac.opt
			[F]TicTac.plg
	[D]p3
		[D]TicTac
			[D]Debug
				[F]TicTac.exe
				[F]TicTac.ilk
				[F]TicTac.obj
				[F]TicTac.pch
				[F]TicTac.pdb
				[F]vc60.idb
				[F]vc60.pdb
			[F]TicTac.cpp
			[F]TicTac.dsp
			[F]TicTac.dsw
			[F]TicTac.h
			[F]TicTac.ncb
			[F]TicTac.opt
			[F]TicTac.plg
		[D]TT
			[D]Debug

可以清楚的看到层级关系!


win32 api遍历文件,进程

// cmd_mfc.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include #include #include #include using n...
  • earbao
  • earbao
  • 2014年03月14日 12:11
  • 1362

win32下,遍历目录下的文件和子目录

win32下,遍历目录下的文件和子目录
  • zsy19881226
  • zsy19881226
  • 2016年06月14日 14:40
  • 2213

如何递归遍历磁盘文件

遍历磁盘文件的API为FindFirstFile和FindNextFile 其原型如下://INVALID_HANDLE_VALUE 表示失败 HANDLE FindFirstFile( LPC...
  • qq_18297675
  • qq_18297675
  • 2016年05月04日 10:43
  • 419

mfc、win32 程序的区别

从尽可能多的角度去描述。
  • shanxuezhe
  • shanxuezhe
  • 2016年01月08日 09:44
  • 2381

[Win32] 文件系统操作

上一节讲了文件同步读写,这次就说说文件系统的操作。 文件系统,简单理解一下,因为磁盘上数据有他的存储方式,而应用程序如果对每种磁盘格式都有了解的话,无疑太难实现,而且兼容性也无法保证,因此,操作系统就...
  • zuishikonghuan
  • zuishikonghuan
  • 2015年07月20日 08:48
  • 2809

在Win32应用程序中使用MFC类库(转)

在Win32应用程序中使用MFC类库(转)  转发   评论 2010-04-30 10:38     由于MFC中的辅助类,如 CFileDialog,CFileFind,CString等使用...
  • susubuhui
  • susubuhui
  • 2013年08月03日 09:15
  • 6322

mfc与win32区别

MFC就是 微软给你包装了的库,提供了很多扩展功能,以及高级功能,这样方便你使用,而不是自己从头调用API来实现 而API由于是MFC下一层,自然实现更灵活,可以根据你的需要来使用,不会被MFC类库所...
  • chenzhisi
  • chenzhisi
  • 2014年03月17日 14:53
  • 767

windows遍历进程与杀死进程

windows下遍历进程有多种方式: 进程快照:CreateToolhelp32Snapshot; 进程状态API:PSAPI; 在psapi中主要使用到的方法有: EnumProcesses——...
  • sowhat_Ah
  • sowhat_Ah
  • 2015年02月04日 12:44
  • 17398

初学者必看:VC++、Win32 SDK、MFC的区别

这是一个初进行开发人员都可能遇到过的概念不清的问题,自己当年也同样有过误解,做技术我感觉一定要专,但是,不代表毫不关心相关的知识,至少概念层次上要知道,所以,这里还是再把这些内容纪录下来,好记性不如烂...
  • lichen18848950451
  • lichen18848950451
  • 2017年03月29日 11:37
  • 1921

MFC动态链接库和WIN32动态链接库 及区别

(1)DLL的构成       每个应用程序都有一个入口函数WinMain,而每个DLL也有一个入口函数DllMain。DLL跟应用程序一样都含有资源、数据段和代码段。DLL跟应用程序的差别主要...
  • slj_win
  • slj_win
  • 2014年06月18日 22:02
  • 1119
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[MFC]利用Win32 API遍历文件系统
举报原因:
原因补充:

(最多只允许输入30个字)