Windows下,在VS中开发,C++遍历文件夹下文件。

在Windows下,遍历文件所用到的函数和结构体,需要在程序中包含头文件#include <io.h>,在VS中,头文件io.h实际上是包含了另一个头文件corecrt_io.h的,所以需要用到的函数和结构体也都是包含在corecrt_io.h这个头文件中的。

首先是遍历文件的时候用于存储文件信息的结构体_finddata_t,_finddata_t在头文件中是一个宏定义:

#define _finddata_t _finddata64i32_t

而_finddata64i32_t的结构体定义如下:

struct _finddata64i32_t
{
    unsigned attrib;
    __time64_t time_create; // -1 for FAT file systems
    __time64_t time_access; // -1 for FAT file systems
    __time64_t time_write;
    _fsize_t size;
    char name[260];
};

也就是这个结构体中包含了六个信息,文件属性(attrib),创建时间(time_create),最近访问时间(time_access)、最近写入时间(time_write)、文件大小(size)和文件名(name)。文件属性有以下几种:

#define _A_NORMAL 0x00 // Normal file - No read/write restrictions,普通文件,无读写限制
#define _A_RDONLY 0x01 // Read only file,只读文件
#define _A_HIDDEN 0x02 // Hidden file,隐藏文件
#define _A_SYSTEM 0x04 // System file,系统文件
#define _A_SUBDIR 0x10 // Subdirectory,子目录
#define _A_ARCH 0x20 // Archive file,存档文件

之后要遍历文件夹,需要用到三个函数_findfirst、_findnext、_findclose,前两个是宏定义,指向了两个函数:

#define _findfirst _findfirst64i32
#define _findnext _findnext64i32

1、_findfirst的函数声明为:

_Success_(return != -1) _Check_return_ _ACRTIMP intptr_t __cdecl _findfirst64i32( _In_z_ char const* _FileName, _Out_  struct _finddata64i32_t* _FindData );

这个函数是查找符合条件的第一个实例,第一个参数_FileName是一个通配符,可以是”*.*”或者”xxxxx.*”,或者”xxxxxx/*”,或者”*.txt”等方式,第二个参数_FindData则是用于存储当前查找到的文件的信息。如果查找成功则返回intptr_t类型的句柄,该句柄不是指针,而是

typedef int intptr_t;

如果失败,返回-1,成功则返回句柄。

2、_findnext的函数声明为:

_Success_(return != -1) _Check_return_ _ACRTIMP int __cdecl _findnext64i32( _In_  intptr_t _FindHandle, _Out_ struct _finddata64i32_t* _FindData );

函数是查找句柄的下一个符合条件的实例,输入变量_FindHandle就是当前的句柄,_FindData则是下一个句柄的实例的文件信息,失败返回-1, 成功返回0。

3、_findclose的函数声明为:

_Check_return_opt_ _ACRTIMP int __cdecl _findclose( _In_ intptr_t _FindHandle );

则是根据句柄关闭查找,成功返回0,失败返回-1;

例子:

#include <io.h>
void getFiles(std::string path, std::vector<std::string>& files, std::vector<std::string>& names) 
{
     //文件句柄,win10用long long,win7用long就可以了
     long hFile = 0;
     //文件信息 
     struct _finddata_t fileinfo; 
     std::string p; 
     if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) 
     { 
         do 
         { 
             //如果是目录,迭代之 //如果不是,加入列表 
             if ((fileinfo.attrib & _A_SUBDIR)) 
             { 
                 if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) 
                 { 
                     getFiles(p.assign(path).append("\\").append(fileinfo.name), files, names);
                 } 
             }
             else 
             { 
                 files.push_back(p.assign(path).append("\\").append(fileinfo.name)); 
                 names.push_back(fileinfo.name); 
             } 
         }while (_findnext(hFile, &fileinfo) == 0);
         _findclose(hFile); 
     } 
}

觉来窗牖空,寥落雨声晓。

良游怨迟暮,末事惊纷扰。

为问经世心,古人难尽了。

  -- 柳宗元 《独觉》