GetFileList.h
#pragma once
#define _AFXDLL
#include <iostream>
#include <vector>
#include <afx.h>
#include <atlstr.h>
#ifdef UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif
//
// @brief: 获取文件扩展名
// @param: strfileName 文件名, 如: test.exe
// @param: bIncludeDot 是否包含 . 号
// @ret: 扩展名 如 test.exe bIncludeDot = false 时返回 exe, bIncludeDot = true 时返回 .exe,
CString GetFileExtension(
const CString& strfileName,
bool bIncludeDot = false
);
//
// @brief: 获取目录下文件路径
// @param: fileList 文件路径字符串容器
// @param: dir 指定目录
// @param: extList 扩展名过滤列表, 如: {("exe"), ("txt")}
// @param: depth 目录深度 如: 0:指定目录为根目录, 遍历0层子目录
// @ret: void
void GetFileList(
std::vector<CString>& fileList,
const CString& dir,
const std::vector<CString>& extList = {},
int depth = MAX_PATH,
bool bIgnoreCase = true);
//
// @brief: 获取文件扩展名
// @param: strfileName 文件名, 如: test.exe
// @param: bIncludeDot 是否包含 . 号
// @ret: 扩展名 如 test.exe bIncludeDot = false 时返回 exe, bIncludeDot = true 时返回 .exe,
_tstring GetFileExtName(
const _tstring& strfileName,
bool bIncludeDot = false
);
//
// @brief: 获取目录下文件路径
// @param: fileList 文件路径字符串容器
// @param: dir 指定目录
// @param: extList 扩展名过滤列表, 如: {("exe"), ("txt")}
// @param: depth 目录深度 如: 0:指定目录为根目录, 遍历0层子目录
// @ret: void
void GetFileList(
std::vector<_tstring>& fileList,
const _tstring& dir,
const std::vector<_tstring>& extList = {},
int32_t depth = MAX_PATH,
bool bIgnoreCase = true
);
GetFileList.cpp
#include "GetFileList.h"
#include <tchar.h>
_tstring GetFileExtName(const _tstring& strfileName, bool bIncludeDot/* = false*/)
{
_tstring strExtName = strfileName;
size_t nExtPos = strExtName.find_last_of(_T('.'));
if (_tstring::npos == nExtPos)
{
return _T("");
}
if (bIncludeDot)
{
strExtName.erase(0, nExtPos);
}
else
{
strExtName.erase(0, nExtPos + 1);
}
return strExtName;
}
void GetFileList(
std::vector<_tstring>& fileList,
const _tstring& dir,
const std::vector<_tstring>& extList /* = {} */,
int32_t depth /* = MAX_PATH */,
bool bIgnoreCase/* = true*/
)
{
//到达深度限制返回
if (depth < 0)
{
return;
}
WIN32_FIND_DATA findData = { 0 };
HANDLE hFindHandle = INVALID_HANDLE_VALUE;
hFindHandle = FindFirstFile((dir + _T("\\*.*")).c_str(), &findData);
if (INVALID_HANDLE_VALUE == hFindHandle)
{
return;
}
_tstring strName;
do
{
strName = findData.cFileName;
//非目录
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
if (extList.empty())
{
fileList.emplace_back(dir + _T("\\") + strName);
}
else
{
//获取扩展名
_tstring strExtName = GetFileExtName(strName, false);
//大小写比较区分
if (bIgnoreCase)
{
//进行扩展名过滤
for (auto& item : extList)
{
if (0 == _tcsicmp(item.c_str(), strExtName.c_str()))
{
fileList.emplace_back(dir + _T("\\") + strName);
}
}
}
else
{
//进行扩展名过滤
for (auto& item : extList)
{
if (item == strExtName)
{
fileList.emplace_back(dir + _T("\\") + strName);
}
}
}
}
continue;
}
//上一级目录与当前目录跳过
if (0 == _tcscmp(findData.cFileName, _T(".")) || 0 == _tcscmp(findData.cFileName, _T("..")))
{
continue;
}
(void)GetFileList(fileList, dir + _T("\\") + strName, extList, depth - 1);
} while (::FindNextFile(hFindHandle, &findData));
::FindClose(hFindHandle);
}
CString GetFileExtension(const CString& strfileName, bool bIncludeDot /* = false*/)
{
if (strfileName == _T(""))
{
return _T("");
}
CString strFileExtension = strfileName;
int i64Index = strFileExtension.ReverseFind(_T('.'));
if (-1 == i64Index)
{
return _T("");
}
if (!bIncludeDot)
{
strFileExtension = strFileExtension.Mid(i64Index + 1);
}
else
{
strFileExtension = strFileExtension.Mid(i64Index);
}
return strFileExtension;
}
void GetFileList(
std::vector<CString>& fileList,
const CString& dir,
const std::vector<CString>& extList/* = {}*/,
int depth/* = 1*/,
bool bIgnoreCase/* = true*/)
{
if (depth < 0)
{
return;
}
CFileFind finder;
// 总文件夹,开始遍历
CString strFind = dir + _T("\\*.*");
BOOL isNotEmpty = finder.FindFile(strFind);
while (isNotEmpty)
{
isNotEmpty = finder.FindNextFile(); // 查找文件
CString filename = finder.GetFilePath(); // 获取文件的路径,可能是文件夹,可能是文件
if (!finder.IsDirectory())
{
// 如果是文件则加入文件列表
CString fileExt = GetFileExtension(filename, false);
if (extList.empty())
{
fileList.push_back(filename); //将一个文件路径加入容器
}
else
{
//大小写比较区分
if (bIgnoreCase)
{
for (auto& item : extList)
{
if (0 == item.CompareNoCase(fileExt))
{
fileList.push_back(filename); //将一个文件路径加入容器
}
}
}
else
{
for (auto& item : extList)
{
if (item == fileExt)
{
fileList.push_back(filename); //将一个文件路径加入容器
}
}
}
}
}
else
{
// 递归遍历用户文件夹,跳过非用户文件夹
if (!(finder.IsDots()))
{
GetFileList(fileList, filename, extList, depth - 1, bIgnoreCase);
}
}
}
}
main.cpp
#include "GetFileList.h"
#include <time.h>
int main()
{
clock_t tBeg;
clock_t tEnd;
std::vector<_tstring> vFileList;
vFileList.clear();
tBeg = clock();
GetFileList(vFileList, _T(R"(C:\Program Files (x86))"));
tEnd = clock();
printf("*.* costTime: %dms, file count: %zd\n", tEnd - tBeg, vFileList.size());
vFileList.clear();
tBeg = clock();
GetFileList(vFileList, _T(R"(C:\Program Files (x86))"), { _T("exe") });
tEnd = clock();
printf("*.exe costTime: %dms, file count: %zd\n", tEnd - tBeg, vFileList.size());
vFileList.clear();
tBeg = clock();
GetFileList(vFileList, _T(R"(C:\Program Files (x86))"), { _T("txt") });
tEnd = clock();
printf("*.txt costTime: %dms, file count: %zd\n", tEnd - tBeg, vFileList.size());
system("pause");
return 0;
}