本文可转载,转载请注明出处:http://www.cnblogs.com/collectionne/p/6815924.html。html
前面的一篇文章咱们讲了用Windows API遍历一个目录下的全部文件,此次咱们讲用一种Windows/Linux通用的方法遍历一个目录下的全部文件。ios
Windows/Linux的IDE都会提供一个头文件——<io.h>。看名字,彷佛是关于I/O的,可是实际上它还提供了相似于WIN32_FIND_DATA、FindFirstFile()、FindNextFile()和FindClose()的查找文件的功能。函数
_finddata_t结构spa
_finddata_t结构用来记录查找到的文件的信息。实际上有_finddata32_t、_finddata32i64_t、_finddata64i32_t、_finddata64_t、_wfinddata32_t、_wfinddata32i64_t、_wfinddata64i32_t、_wfinddata64_t八个结构,但都只是在32位/64位整数和字符类型上有所区别,但总体上相同。大体定义以下(MSDN):指针
struct _finddata_t { unsigned attrib; size_t time_create; size_t time_access; size_t time_write; _fsize_t size; char name[_MAX_PATH]; };
对于不一样的_finddata_t结构,time_create、time_access和time_write的类型为_time32_t或_time64_t,size的类型为_fsize_t或__int64,name为char[_MAX_PATH]或wchar_t[_MAX_PATH]。code
attribhtm
unsigned类型,文件属性。blog
time_createci
_time32_t/_time64_t类型,文件建立时间(FAT文件系统为-1)。以UTC格式存储,若是须要转换成当地时间,使用localtime_s()。资源
time_access
_time32_t/_time64_t类型,文件最后一次被访问的时间(FAT文件系统为-1)。以UTC格式存储,若是须要转换成当地时间,使用localtime_s()。
time_write
_time32_t/_time64_t类型,文件最后一次被写入的时间。以UTC格式存储,若是须要转换成当地时间,使用localtime_s()。
size
_fsize_t/__int64类型,文件的长度(以字节为单位)。
name
char[_MAX_PATH]/wchar_t[_MAX_PATH]类型,文件/目录名,不包含路径。
对于不支持文件建立时间、文件上一次访问时间的文件系统,time_create和time_access为-1。
_MAX_PATH在stdlib.h中被定义为260。
通常_finddata_t被定义为_finddata32_t/_finddata64i32_t,_wfinddata_t被定义为_wfinddata32_t/_wfinddata64i32_t。为方便,下文中将_finddata_t和_wfinddata_t统称为_finddata_t。
文件属性常量
一个文件/目录能够有多种属性,每种属性能够是下面列出的属性之一。
_A_ARCH
档案。文件被BACKUP指令改变或清除时被设置。值:0x20。
_A_HIDDEN
隐藏。使用DIR指令通常看不到,除非使用/AH选项。值:0x02。
_A_NORMAL
普通。文件没有更多属性被设置,能够没有限制地被读或写。值:0x00。
_A_RDONLY
只读。不能以“写”为目的打开该文件,而且不能建立同名的文件。值:0x01。
_A_SUBDIR
子目录。值:0x10。
_A_SYSTEM
系统文件。使用DIR指令通常看不见,除非使用/A或/A:S选项。值:0x04。
要检查x是否含有某个属性a,能够用x & a进行检查。指定多个属性可使用按位or运算符,例如_A_SYSTEM | _A_RDONLY | _A_HIDDEN。
通配符(wildcards)
遍历文件目录时须要使用通配符,详见个人另外一篇文章。
_findfirst()/_findnext()/_findclose()函数
_findfirst()函数
intptr_t _findfirst( const char * filespec, struct _finddata_t *fileinfo );
实际上_findfirst()有10个版本,这里只列出一个。
filespec
const char */const wchar_t *类型,目标文件说明(可包含通配符)。
fileinfo
_finddata_t *类型,函数将会填入文件/目录信息。
返回值
若是成功,返回一个惟一的搜索句柄标识一个或一组和filespec说明匹配的文件,能够用于接下来的_findnext()和_findclose()函数。不然_findfirst()返回-1。注意,intptr_t并非指针类型,只是int或__int64的typedef。
_findnext()函数
int _findnext( intptr_t handle, struct _finddata_t *fileinfo );
handle
intptr_t类型,搜索句柄。
fileinfo
_finddata_t *类型,函数将会填入文件/目录信息。
返回值
若是成功,返回0,不然返回-1。若是没有更多可以找到的文件了,也会致使失败。
_findclose()函数
int _findclose( intptr_t handle );
关闭搜索句柄并释放相应的资源。
handle
搜索句柄。
返回值
成功返回0,失败返回-1。
程序代码
1. 遍历目录下的全部文件
#include <iostream> #include <cstring> // for strcat() #include <io.h> using namespace std; void listFiles(const char * dir); int main() { char dir[200]; cout << "Enter a directory (ends with \'\\\'): "; cin.getline(dir, 200); strcat(dir, "*.*"); // 在要遍历的目录后加上通配符 listFiles(dir); return 0; } void listFiles(const char * dir) { intptr_t handle; _finddata_t findData; handle = _findfirst(dir, &findData); // 查找目录中的第一个文件 if (handle == -1) { cout << "Failed to find first file!\n"; return; } do { if (findData.attrib & _A_SUBDIR && strcmp(findData.name, ".") == 0 && strcmp(findData.name, "..") == 0 ) // 是不是子目录而且不为"."或".." cout << findData.name << "\t<dir>\n"; else cout << findData.name << "\t" << findData.size << endl; } while (_findnext(handle, &findData) == 0); // 查找目录中的下一个文件 cout << "Done!\n"; _findclose(handle); // 关闭搜索句柄 }
程序遍历目录下的全部文件/目录,若是是文件则输出文件大小。
注意_findnext()函数成功返回0,所以要加上==0或!=-1进行判断,不能省略。
此外还有一个值得注意的地方:
if (findData.attrib & _A_SUBDIR && strcmp(findData.name, ".") && strcmp(findData.name, "..") ) ...
使用_findfirst()、_findnext()进行搜索时,可能会获得"."和".."两个文件夹名。这两个值能够忽略。
2. 遍历目录中的全部文件
注意是“目录中”而不是“目录下”,这个程序将会遍历一个目录里包含的全部文件。
#include <iostream> #include <cstring> // for strcpy(), strcat() #include <io.h> using namespace std; void listFiles(const char * dir); int main() { char dir[200]; cout << "Enter a directory: "; cin.getline(dir, 200); listFiles(dir); return 0; } void listFiles(const char * dir) { char dirNew[200]; strcpy(dirNew, dir); strcat(dirNew, "\\*.*"); // 在目录后面加上"\\*.*"进行第一次搜索 intptr_t handle; _finddata_t findData; handle = _findfirst(dirNew, &findData); if (handle == -1) // 检查是否成功 return; do { if (findData.attrib & _A_SUBDIR) { if (strcmp(findData.name, ".") == 0 || strcmp(findData.name, "..") == 0) continue; cout << findData.name << "\t<dir>\n"; // 在目录后面加上"\\"和搜索到的目录名进行下一次搜索 strcpy(dirNew, dir); strcat(dirNew, "\\"); strcat(dirNew, findData.name); listFiles(dirNew); } else cout << findData.name << "\t" << findData.size << " bytes.\n"; } while (_findnext(handle, &findData) == 0); _findclose(handle); // 关闭搜索句柄 }