Window文件目录遍历 和 WIN32_FIND_DATA 结构(非常详细的中文注释)
第一部分 *百度百科提供的内容总结:WIN32_FIND_DAT
第二部分 *程序实例
第三部分 *一篇使用FindFirstFile和FindNextFile函数的博文
第一部分
1.关于文件的全部属性信息,有以下以下9种:
文件的标题名、文件的属性(只读、存档,隐藏等)、文件的创建时间、文件的最后访问时间、文件的最后修改时间、文件大小的高位双字、文件大小的低位双字、保留、保留。在这里只有文件标题名和文件的长度可以通过CFile类比较方便的获得,而对于其他几种属性的获取和设置就无能为力了。
- typedef struct _WIN32_FIND_DATA
- {
- DWORD dwFileAttributes; //文件属性
- FILETIME ftCreationTime; // 文件创建时间
- FILETIME ftLastAccessTime; // 文件最后一次访问时间
- FILETIME ftLastWriteTime; // 文件最后一次修改时间
- DWORD nFileSizeHigh; // 文件长度高32位
- DWORD nFileSizeLow; // 文件长度低32位
- DWORD dwReserved0; // 系统保留
- DWORD dwReserved1; // 系统保留
- TCHAR cFileName[ MAX_PATH ]; // 长文件名(最多可达 255 个字符的长文件名),带句点和扩展名
- TCHAR cAlternateFileName[ 14 ]; //8.3格式文件名(句点前最多有8个字符,而扩展名最多可以有3个字符)
- } WIN32_FIND_DATA, *PWIN32_FIND_DATA;
可以通过FindFirstFile()函数根据当前的文件存放路径查找该文件来把待操作文件的相关属性读取到WIN32_FIND_DATA结构中去:
- WIN32_FIND_DATA ffd ;
- HANDLE hFind = FindFirstFile("c:\\test.dat",&ffd);
在使用这个结构时不能手工修改这个结构中的任何数据,结构对于开发人员来说只能作为一个只读数据,其所有的成员变量都会由系统完成填写。在MSDN帮助中可以查找到关于WIN32_FIND_DATA结构的更加详细的说明。
2.文件属性信息的获取与更改
为了更好的保存获取到的文件属性信息,对应于文件属性构造一个自定义的FILE_INFO数据结构,获取的属性信息可暂存于此:
- typedef struct _FILE_INFO
- {
- TCHAR szFileTitle[128]; //文件的标题名
- DWORD dwFileAttributes; //文件的属性
- FILETIME ftCreationTime; //文件的创建时间
- FILETIME ftLastAccessTime; //文件的最后访问时间
- FILETIME ftLastWriteTime; //文件的最后修改时间
- DWORD nFileSizeHigh; //文件大小的高位双字
- DWORD nFileSizeLow; //文件大小的低位双字
- DWORD dwReserved0; //保留,为0
- DWORD dwReserved1; //保留,为0
- } FILE_INFO, * PFILE_INFO;
首先用FindFirstFile()函数将文件属性获取到WIN32_FIND_DATA 结构对象FindFileData中去,之后可以用FindClose()将其关闭,并把FindFileData中的有关文件属性信息的内容复制到自定义结构FILE_INFO的结构对象FileInfo中备用。下面是关于这部分描述的部分关键代码:
- //声明结构对象
- FILE_INFO FileInfo;
- WIN32_FIND_DATA FindFileData;
- ……
- //获取文件属性信息
- FindClose(FindFirstFile("Test.txt",&FindFileData));
- memset(&FileInfo,0,sizeof(FILE_INFO));
- ……
- //将文件属性信息保存到FileInfo中备用
- strcpy(FileInfo.szFileTitle,myFile.GetFileTitle());
- FileInfo.dwFileAttributes = FindFileData.dwFileAttributes;
- FileInfo.ftCreationTime = FindFileData.ftCreationTime;
- FileInfo.ftLastAccessTime = FindFileData.ftLastAccessTime;
- FileInfo.ftLastWriteTime = FindFileData.ftLastWriteTime;
- FileInfo.nFileSizeHigh = FindFileData.nFileSizeHigh;
- FileInfo.nFileSizeLow = FindFileData.nFileSizeLow;
- ……
在获取到文件的原始属性信息后既可以原封不动的将属性重新写到文件,也可以对其中某一项或某几项属性内容进行修改后再行写入文件,从而达到更改文件属性的目的。比如可以用SetFileTime()函数设置文件的创建时间、最近一次访问时间以及最近一次修改的时间等等:
- SetFileTime((HANDLE)destFile.m_hFile, //待写入的文件句柄
- &FileInfo.ftCreationTime, //文件的创建时间
- &FileInfo.ftLastAccessTime, //文件最近一次的访问时间
- &FileInfo.ftLastWriteTime); //文件最近一次的修改时间
- 也可以用SetFileAttributes() 函数实现对文件属性的修改:
- SetFileAttributes(FileInfo.szFileTitle,FileInfo.dwFileAttributes);
- BOOL WINAPI MoveFile(LPCSTR Existing, LPCSTR Target);
- MoveFile("D:\\Temp\\a.txt", "E:\\MyPath\\b.txt"); 将D:\Temp\a.txt移动到E:\MyPath并改名为b.txt
- BOOL WINAPI CopyFile(LPCSTR oldFileName, LPCSTR newFileName, BOOL failIfExists);
- oldFileName: 原始文件名;
- newFileName: 目标文件名;
---------------------------------百度百科引用内容结束----------------
第二部分
5. _access(char *); //判断文件或文件夹路径是否合法 <direct.h>
_chdir(char *); //设置当前目录 <direct.h>
6.补充findfirst, findnext 和_findfirst, _findnext搜索磁盘目录
四个函数全部属于 io.h 头文件中
- 1. int findfirst(char *pathname, struct ffblk *ffblk, int attrib);
- 2. int findnext(struct ffblk *ffblk);
程序例1:
- /*用于文件的查找和删除*/
- #include <stdio.h>
- #include <dir.h>
- //两个函数需要定义一个结构体来存储函数返回的数据。结构体如下:
- struct ffblk
- {
- char ff_reserved[21]; /*DOS保留字*/
- char ff_attrib; /*文件属性*/
- int ff_ftime; /*文件时间*/
- int ff_fdate; /*文件日期*/
- long ff_fsize; /*文件长度*/
- char ff_name[13]; /*文件名*/
- }
- //将结构体中的ff_name[13]显示出来即可。
- int main(void)
- {
- struct ffblk ffblk;
- int done;
- printf("Directory listing of *.*\n");
- done = findfirst("*.*",&ffblk,0);
- while (!done)
- {
- printf(" %s\n", ffblk.ff_name);
- done = findnext(&ffblk);
- }
- return 0;
- }
- 3. int _findnext(intptr_t handle,struct _finddata_t *fileinfo); \\搜索与_findfirst函数提供的文件名称匹配的下一个实例,若成功则返回0,否则返回-1
- 4. long _findfirst( char *filespec, struct _finddata_t *fileinfo ); \\搜索与指定的文件名称匹配的第一个实例,若成功则返回第一个实例的句柄,否则返回-1L
- 参数说明:struct _finddata_t的定义见于io.h
- struct _finddata_t
- {
- unsigned attrib;
- time_t time_create; /* -1 for FAT file systems */
- time_t time_access; /* -1 for FAT file systems */
- time_t time_write;
- _fsize_t size;
- char name[260];
- };
- shmiloveyou 补充:sttrib参数有如下类型:
- _A_ARCH(存档)
- _A_HIDDEN(隐藏)
- _A_NORMAL(正常)
- _A_RDONLY(只读)
- _A_SUBDIR(文件夹)
- _A_SYSTEM(系统)
程序例2--遍历指定目录下的文件和文件夹:
- ////shmiloveyou:特别注意,这个实例有个严重的问题,遍历会失败
- ///原作者已经不详,我会在“程序例3中用实例指出问题所在”
- 显示所有的文件:
- #include <io.h>
- #include <iostream>
- #include <string>
- #include <windows.h>
- using namespace std;
- string sRoot = "D:";
- string sSuffix = "\\test\\*.*"; // 后缀 //shmiloveyou:这样写只会查找文件,"\\*"表示匹配所有包括文件夹
- void Move(string sPath);
- void main()
- {
- Move(sRoot);
- system("pause");
- }
- void Move(string sPath)
- {
- struct _finddata_t file;
- long hFile, hFileNext;
- string sPathLast = sPath + sSuffix; // sPathLast = "D:\\test\\*.*"
- hFile = _findfirst(sPathLast.c_str(), &file);
- if(hFile == -1)
- {
- cout<<"文件不存在."<<endl;
- return;
- }
- else
- {
- cout<<file . name<<endl;
- }
- hFileNext = _findnext(hFile, &file); //shmiloveyou:这句多余
- while(_findnext(hFile, &file) == 0)
- { //shmiloveyou:没有过滤掉本级目录'.'和父级目录'..'
- if(file.attrib == _A_SUBDIR)
- {
- string sAddPath = sPath;
- sAddPath += "\\";
- sAddPath += file . name;
- cout<<"目录:"<<sAddPath<<endl;
- Move(sAddPath);
- }
- else
- {
- string sAddPath = sPath;
- sAddPath += "\\";
- sAddPath += file . name;
- cout<<"文件:"<<sAddPath<<endl;
- }
- }
- //shmiloveyou:作者没有关闭文件句柄 _closefile(hFile);
- }
运行结果类似这样,总之是失败的:
总结:
造成这种结果是由于,作者没有考虑“本级目录和父目录”这个概念,因为_findfirst函数最先查找的就是本级目(此时file.name[0] == '.'必成立),而且还会查找父级目录(此时file.name[0]和file.name[1]都等于'.')。这就是为什么上面的图片中会有那么多的‘.’和‘..’。怎么办呢?添加一段程序处理这个问题,只要“ file.name[0] == '.' ”成立就继续while循环。程序如下:
程序例3:(shmiloveyou -- 原创 2014-01-04)
- #include <io.h>
- #include <iostream>
- #include <string>
- #include <windows.h>
- #include <direct.h>
- using namespace std;
- string sRoot = "G:"; //根目录
- string sSuffix = "\\DesignModal"; //中间路径
- string sEnd = "\\"; //路径末尾追加的部分
- void Move(string sPath);
- int main(void)
- {
- string sPath = sRoot + sSuffix; //sPath="G:\\DesignModal"
- Move(sPath);
- system("pasue");
- return 0;
- }
- void Move( string sPath)
- {
- struct _finddata_t file;
- memset(&file, 0, sizeof(file)); //初始化结构
- long hFile;
- string sPathLast = sPath; //sPathLast="G:\\DesignModal"
- if (_chdir(sPathLast.c_str()) != 0) //_chdir函数设置当前目录
- {
- cerr << "当前目录设置失败!" << endl;
- exit(-1);
- }
- hFile = _findfirst("*",&file); //参数1:char *类型,"*"表示通配符,可以查找文件、文件夹
- if(hFile == -1)
- {
- cout << " 遍历失败!" << endl;
- return ;
- }
- do
- {
- if(file.name[0] == '.') //过滤本级目录和父目录 此处就是“程序例2”中的病根所在
- continue;
- if(file.attrib == _A_SUBDIR) //子文件夹
- {
- string sAddPath = sPath;
- sAddPath += "\\";
- sAddPath += file.name;
- cout << "目录:" << sAddPath << endl;
- Move(sAddPath); //递归遍历
- }
- else
- {
- string sAddPath = sPath;
- sAddPath += "\\";
- sAddPath += file.name;
- cout << "文件:" << sAddPath << endl;
- }
- }while(_findnext(hFile,&file) == 0); //没有找到文件或文件夹
- _findclose(hFile); //一定记得关闭文件句柄
- }
运行效果:
第三部分
参考博文:http://blog.csdn.net/dyx1024/article/details/2759413【转】
上面的博文中作者使用FindFirstFile和FindNextFile这两个函数实现指定目录遍历的。
避免参考博文丢失(最初博文地址已经失效),遂引用如下:
- //转自:http://www.vcgood.com/forum_posts.asp?TID=2261&PN=1 地址已经失效
- //用于输出指定目录下的所有文件的文件名,包括子目录。
- 版本1:用string处理,方便,容易理解.
- #include <windows.h>
- #include <iostream>
- #include <string>
- using namespace std;
- bool IsRoot(string Path)
- {
- string Root;
- Root=Path.at(0)+"://";
- if(Root==Path)
- return true;
- else
- return false;
- }
- void FindInAll(string Path)
- {
- string szFind;
- szFind=Path;
- if(!IsRoot(szFind))
- szFind+="//";
- szFind+="*.*";
- WIN32_FIND_DATA FindFileData;
- HANDLE hFind=FindFirstFile(szFind.c_str(),& FindFileData);
- if(hFind==INVALID_HANDLE_VALUE)
- return ;
- do
- {
- if(FindFileData.cFileName[0]=='.') //过滤本级目录和父目录
- continue;
- if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //如果找到的是目录,则进入此目录进行递归
- {
- string szFile;
- if(IsRoot(Path))
- szFile=Path+FindFileData.cFileName;
- else
- szFile=Path+"//"+FindFileData.cFileName;
- FindInAll(szFile);
- }
- else //找到的是文件
- {
- string szFile;
- if(IsRoot(Path))
- szFile=Path+FindFileData.cFileName;
- else
- szFile=Path+"//"+FindFileData.cFileName;
- cout<<szFile<<endl;
- cout<<FindFileData.cFileName<<endl;
- }
- }
- while(FindNextFile(hFind,& FindFileData));
- FindClose(hFind);
- }
- int main()
- {
- FindInAll("D://C++");
- return 0;
- }
- 版本2:编译器的通用性更强
- #include <windows.h>
- #include <iostream>
- using namespace std;
- BOOL IsRoot(LPCTSTR lpszPath)
- {
- TCHAR szRoot[4];
- wsprintf(szRoot,"%c://",lpszPath[0]);
- return (lstrcmp(szRoot,lpszPath)==0);
- }
- void FindInAll(::LPCTSTR lpszPath)
- {
- TCHAR szFind[MAX_PATH];
- lstrcpy(szFind,lpszPath); //windows API 用lstrcpy,不是strcpy
- if(!IsRoot(szFind))
- lstrcat(szFind,"//");
- lstrcat(szFind,"*.*"); //找所有文件
- WIN32_FIND_DATA wfd;
- HANDLE hFind=FindFirstFile(szFind,& wfd);
- if(hFind==INVALID_HANDLE_VALUE) // 如果没有找到或查找失败
- return;
- do
- {
- if(wfd.cFileName[0]=='.')
- continue; //过滤这两个目录
- if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- TCHAR szFile[MAX_PATH];
- if(IsRoot(lpszPath))
- wsprintf(szFile,"%s%s",lpszPath,wfd.cFileName);
- else
- wsprintf(szFile,"%s//%s",lpszPath,wfd.cFileName);
- FindInAll(szFile); //如果找到的是目录,则进入此目录进行递归
- }
- else
- {
- TCHAR szFile[MAX_PATH];
- if(IsRoot(lpszPath))
- wsprintf(szFile,"%s%s",lpszPath,wfd.cFileName);
- else
- wsprintf(szFile,"%s//%s",lpszPath,wfd.cFileName);
- printf("%s/n",szFile); //对文件进行操作
- }
- }
- while(FindNextFile(hFind,&wfd));
- FindClose(hFind); //关闭查找句柄
- }
- int main()
- {
- FindInAll("D://C++");
- return 0;
- }
http://blog.csdn.net/qq2399431200/article/details/11878611
Window文件目录遍历 和 WIN32_FIND_DATA 结构(非常详细的中文注释)的更多相关文章
- STM32 IAP程序 源码 和测试代码 有详细的中文注释
http://bbs.21ic.com/forum.php?mod=viewthread&tid=588265&reltid=624002&pre_pos=2&ext= ...
- Android安全开发之ZIP文件目录遍历
1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件.如果被覆盖掉的文件是动态链接s ...
- HighCharts学习笔记(二)HighCharts结构及详细配置
HighCharts结构及详细配置: 一.HighCharts整体结构: 通过查看API文档我们知道HighCharts结构如下:(API文档在文章后面提供下载) var chart = new Hi ...
- Android 安全开发之 ZIP 文件目录遍历
1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在"../"的字符串,攻击者可以利用多个"../"在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原 ...
- Linux 目录结构及详细操作
目录 Linux 目录结构及详细操作 目录结构 目录结构的特点 目录结构挂载 目录结构发展 关闭selinux(了解) 重要目录说明(etc目录说明) 1.网卡配置文件 2.解析配置文件 3.主机名称 ...
- ❤️这应该是Postman最详细的中文使用教程了❤️(新手使用,简单明了)
️这应该是Postman最详细的中文使用教程了️(新手使用,简单明了) 在前后端分离开发时,后端工作人员完成系统接口开发后,需要与前端人员对接,测试调试接口,验证接口的正确性可用性.而这要求前端开发进 ...
- Linux目录结构及详细介绍
/:根目录,位于Linux文件系统目录结构的顶层,一般根目录下只存放目录,不要存放文件,/etc./bin./dev./lib./sbin应该和根目录放置在一个分区中. /bin,/usr/bin:该 ...
- 【Linux】Linux目录结构及详细介绍
00. 目录 01. 常用目录介绍 /:根目录,位于Linux文件系统目录结构的顶层,一般根目录下只存放目录,不要存放文件,/etc./bin./dev./lib./sbin应该和根目录放置在一个分区 ...
- CentOS目录结构超详细版
最近初学Linux 对linux的目录产生了很多疑问,看到这篇文章,让我顿时对目录有了一个清晰的认识!推荐给大家! ------------------------------------------ ...
随机推荐
- 毕设三: spark与phoenix集成插入数据/解析json数组
需求:将前些日子采集的评论存储到hbase中 思路: 先用fastjson解析评论,然后构造rdd,最后使用spark与phoenix交互,把数据存储到hbase中 部分数据: [ { "r ...
- 拉伸按钮背景图片:stretchableImageWithLeftCapWidth:
// 1. 拉伸按钮背景图片 // 1) 登录按钮 UIImage *loginImage = [UIImage imageNamed:@"LoginGreenBigBtn"]; ...
- 有奖试读&征文--当青春遇上互联网,是否能点燃你的创业梦
时至今日,互联网已经切入我们每一个人的工作.生活和学习的每一个角落.利用互联网这个工具,有人游戏,有人购物,有人上课,有人交友,而有那么一部分人去利用它完毕人生最完美的逆袭.相信每一个人心中都有个创业 ...
- Session Redis Nginx
Session + Redis + Nginx 一.Session 1.Session 介绍 我相信,搞Web开发的对Session一定再熟悉不过了,所以我就简单的介绍一下. Session:在计算机 ...
- ElasticSearch的javaAPI之Client
翻译的原文:http://www.elasticsearch.org/guide/en/elasticsearch/client/java-api/current/client.html#node-c ...
- Windows SublimeText内使用NDK编译Android so(不用cygwin)
測试环境: sublime text version 2.0.2, build 2221 和 sublime text stable channel, build 3065 (version3) Wi ...
- hdu 1087 Super Jumping! Jumping! Jumping!(dp 最长上升子序列和)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1087 ------------------------------------------------ ...
- zlib minizip 实现解压zip
#include <stdio.h> #include <string.h> #include "unzip.h" #define dir_delimter ...
- Qt保存界面配置到注册表
//需要使用QSetting #include<QSettings> 声明函数 protected: void closeEvent(QCloseEvent *event); privat ...
- 如何获得iframe中元素的值
在Web开发时,很多时候会遇到一个问题.我在一个页面嵌入了iframe,并且我想获得这个iframe页面某个元素的值.那么该如何实现这个需求呢? 先来看下演示: 效果演示 iframe1中文本 ...