1.相关知识点:
在实现此功能,主要使用到的函数包含,_findfirst()、_findnext()、_findclose()。通过使用上述函数以及配合结构体 _finddata_t 来达到一个遍历的效果。
_finddata_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];
};
借助这个博主所总结的信息:https://blog.csdn.net/xiexu911/article/details/79990774可以了解到:
其中 unsigned attribute 表示文件的属性,分别有以下几种。
_A_ARCH(存档)
_A_HIDDEN(隐藏)
_A_NORMAL(正常)
_A_RDONLY(只读)
_A_SUBDIR(文件夹)
_A_SYSTEM(系统)
time_t time_create:
这个time_create变量是用来存储文件创建时间的,time_t 类型本质是就是一个整型。
time_t time_access:
文件最后一次被访问的时间。
time_t time_write:
文件最后一次被修改的时间。
然后是文件大小和文件名:
_fsize_t size:
文件的大小。这里的_fsize_t是unsigned long类型,表示文件的字节数。
相关函数介绍
long _findfirst( char *filespec, struct _finddata_t *fileinfo );
返回值:
如果查找成功的话,将返回一个long型的唯一的查找用的句柄(就是一个唯一编号)。这个句柄将在_findnext函数中被使用。若失败,则返回-1。
参数:
filespec:标明文件的字符串,可支持通配符。比如:*.c,则表示当前文件夹下的所有后缀为C的文件。
fileinfo :这里就是用来存放文件信息的结构体的指针。这个结构体必须在调用此函数前声明,不过不用初始化,只要分配了内存空间就可以了。
函数成功后,函数会把找到的文件的信息放入这个结构体中。int _findnext( long handle, struct _finddata_t *fileinfo );
返回值:
若成功返回0,否则返回-1。
参数:
handle:即由_findfirst函数返回回来的句柄。
fileinfo:文件信息结构体的指针。找到文件后,函数将该文件信息放入此结构体中。int _findclose( long handle );
返回值:成功返回0,失败返回-1。
参数: handle :_findfirst函数返回回来的句柄。
查找特定文件(包含子文件夹下)
设计思路:
1.用_findfirst查找第一个文件,若成功则用返回的句柄调用_findnext函数查找其他的文件。
2.对查找到的文件进行判断,如果是子文件夹进行递归查找
3.查找到的为文件时,进行类型比对获取自己需要的类型进行存储
代码详细设计
#include<string>
#include<vector>
#include <io.h>
#include <ctype.h>
#define ISPATHPART(c) ((c)=='/'||(c)=='\\')
std::string GetExt(const std::string& strPathFile)
{
if (!strPathFile.empty())
{
int number = 0, index = 0;
if (isascii(strPathFile[0])&&isalpha(strPathFile[0]) && strPathFile[1] == ':')
{
index = 1;
number = index + 1;
}
index++;
int nlen = strPathFile.length();
while (index<nlen)
{
if (ISPATHPART(strPathFile[index]))
{
number = index + 1;
}
index++;
}
if (number >= nlen)
{
return"";
}
int nt = 0;
while (number<index)
{
index--;
if (strPathFile[index] == '.')
{
nt = index;
break;
}
}
return std::string(strPathFile.c_str() + nt, nlen - nt);
}
return "";
}
void get_allsubdir(std::string path, std::vector<std::string>& files, std::string fileType)
{
//在目录后面加上"\\*.*"进行第一次搜索
std::string dir2 = path + "/*.*";
std::vector<int> nums;
intptr_t handle;
_finddata_t findData;
handle = _findfirst(dir2.c_str(), &findData);
if (handle == -1)
{
//检查是否成功
printf("can not found the file ... \n");
return;
}
do
{
if (findData.attrib & _A_SUBDIR) //是否含有子目录
{
//若该子目录为"."或"..",则进行下一次循环
if (strcmp(findData.name, ".") == 0 || strcmp(findData.name, "..") == 0)
continue;
// 在目录后面加上"\\"和搜索到的目录名进行下一次搜索
std::string dirNew = path + "/" + findData.name;
get_allsubdir(dirNew, files, fileType);
}
else //不是子目录,即是文件,则输出文件名和文件的大小
{
std::string tempPath = findData.name;
std::string type = GetExt(tempPath);
if (type == fileType)
{
std::string filePath = path + "/" + findData.name;
files.push_back(filePath);
}
}
} while (_findnext(handle, &findData) == 0);
_findclose(handle); // 关闭搜索句柄
return;
}
int main()
{
std::string path = "F:/cache/shpdata";
std::vector<std::string> vecfiles;
get_allsubdir(path, vecfiles,".png");
return 0;
}
设计中,有一个获取文件类型的操作。想要了解可参考:操作字符串获取文件后缀名-CSDN博客
测试结果
查找特定文件(不包含子文件夹)
设计思路:
和上类似,循环遍历,查找时查找对应文件。
代码详细设计
#include<string>
#include<vector>
#include <io.h>
#include <ctype.h>
void getAllFiles(std::string path, std::vector<std::string>& files, std::string fileType) {
//文件句柄
intptr_t hFile = 0;
_finddata_t fileInfo;
std::string p;
if ((hFile = _findfirst(p.assign(path).append("\\*" + fileType).c_str(), &fileInfo)) != -1) {
do {
files.push_back(p.assign(path).append("\\").append(fileInfo.name));
} while (_findnext(hFile, &fileInfo) == 0);
_findclose(hFile);//关闭句柄
}
}
int main()
{
std::string path = "F:/cache/shpdata";
std::vector<std::string> files;
getAllFiles(path, files, ".shp");
return 0;
}
测试结果
参考文章
C++ 中利用 _findfirst遍历所有文件夹及文件,以及findnext win10报错解决办法_findfirstfile 遍历所有文件包括隐藏属性文件-CSDN博客