C++ 使用FindFirstFile和FindNextFile递归查找具有特定扩展名的文件
我有一个工作代码,它返回给定带有通配符的目录下所有子目录中的所有文件。例如:C++ 使用FindFirstFile和FindNextFile递归查找具有特定扩展名的文件,c++,windows,winapi,recursion,wildcard,C++,Windows,Winapi,Recursion,Wildcard,我有一个工作代码,它返回给定带有通配符的目录下所有子目录中的所有文件。例如:“C://*”。这个很好用。现在,我想知道是否有可能使用某个文件扩展名对所有文件进行递归迭代。例如:“C://*.png”,但不更改代码。我在寻找类似于:“C://*/../*.png”,但我找不到解决方案。我可以使用通配符吗?您需要递归搜索每个子目录。我碰巧有一些代码可以做到这一点,下面的代码可能会有所帮助 #include <functional> #include <io.h> enum
“C://*”
。这个很好用。现在,我想知道是否有可能使用某个文件扩展名对所有文件进行递归迭代。例如:“C://*.png”
,但不更改代码。我在寻找类似于:“C://*/../*.png”
,但我找不到解决方案。我可以使用通配符吗?您需要递归搜索每个子目录。我碰巧有一些代码可以做到这一点,下面的代码可能会有所帮助
#include <functional>
#include <io.h>
enum enumflags {
ENUM_FILE = 1,
ENUM_DIR,
ENUM_BOTH
};
//return value:
// False means that the searching has been aborted by the callback function.
// It will return true otherwise.
bool enumsubfiles(
const std::wstring &dir_with_back_slant, //for example: L"C:\\", L"E:\\test\\"
const std::wstring &filename, //for example: L"123.txt", L"*.exe", L"123.???"
unsigned int maxdepth, //0 means not searching subdirectories, 1 means maximum depth of subdirectories is 1,
// pass -1 to search all the subdirectories.
enumflags flags, //search files, directories, or both.
std::function<bool(const std::wstring &dir_with_back_slant, _wfinddata_t &attrib)> callback
)
{
_wfinddata_t dat;
size_t hfile;
std::wstring fullname = dir_with_back_slant + filename;
std::wstring tmp;
bool ret = true;
hfile = _wfindfirst(fullname.c_str(), &dat);
if (hfile == -1) goto a;
do {
if (!(wcscmp(L".", dat.name) && wcscmp(L"..", dat.name))) continue;
if (((dat.attrib&_A_SUBDIR) && (!(flags&ENUM_DIR))) || ((!(dat.attrib&_A_SUBDIR)) && (!(flags&ENUM_FILE)))) continue;
ret = callback(dir_with_back_slant, dat);
if (!ret) {
_findclose(hfile);
return ret;
}
} while (_wfindnext(hfile, &dat) == 0);
_findclose(hfile);
a:
if (!maxdepth) return ret;
tmp = dir_with_back_slant + L"*";
hfile = _wfindfirst(tmp.c_str(), &dat);
if (hfile == -1) return ret;
do {
if (!(wcscmp(L".", dat.name) && wcscmp(L"..", dat.name))) continue;
if (!(dat.attrib&_A_SUBDIR)) continue;
tmp = dir_with_back_slant + dat.name + L"\\";
ret = enumsubfiles(tmp, filename, maxdepth - 1, flags, callback);
if (!ret) {
_findclose(hfile);
return ret;
}
} while (_wfindnext(hfile, &dat) == 0);
_findclose(hfile);
return ret;
}
我传递给函数的最大深度为1。传递-1以搜索所有子目录。您需要递归搜索每个子目录。我碰巧有一些代码可以做到这一点,下面的代码可能会有所帮助
#include <functional>
#include <io.h>
enum enumflags {
ENUM_FILE = 1,
ENUM_DIR,
ENUM_BOTH
};
//return value:
// False means that the searching has been aborted by the callback function.
// It will return true otherwise.
bool enumsubfiles(
const std::wstring &dir_with_back_slant, //for example: L"C:\\", L"E:\\test\\"
const std::wstring &filename, //for example: L"123.txt", L"*.exe", L"123.???"
unsigned int maxdepth, //0 means not searching subdirectories, 1 means maximum depth of subdirectories is 1,
// pass -1 to search all the subdirectories.
enumflags flags, //search files, directories, or both.
std::function<bool(const std::wstring &dir_with_back_slant, _wfinddata_t &attrib)> callback
)
{
_wfinddata_t dat;
size_t hfile;
std::wstring fullname = dir_with_back_slant + filename;
std::wstring tmp;
bool ret = true;
hfile = _wfindfirst(fullname.c_str(), &dat);
if (hfile == -1) goto a;
do {
if (!(wcscmp(L".", dat.name) && wcscmp(L"..", dat.name))) continue;
if (((dat.attrib&_A_SUBDIR) && (!(flags&ENUM_DIR))) || ((!(dat.attrib&_A_SUBDIR)) && (!(flags&ENUM_FILE)))) continue;
ret = callback(dir_with_back_slant, dat);
if (!ret) {
_findclose(hfile);
return ret;
}
} while (_wfindnext(hfile, &dat) == 0);
_findclose(hfile);
a:
if (!maxdepth) return ret;
tmp = dir_with_back_slant + L"*";
hfile = _wfindfirst(tmp.c_str(), &dat);
if (hfile == -1) return ret;
do {
if (!(wcscmp(L".", dat.name) && wcscmp(L"..", dat.name))) continue;
if (!(dat.attrib&_A_SUBDIR)) continue;
tmp = dir_with_back_slant + dat.name + L"\\";
ret = enumsubfiles(tmp, filename, maxdepth - 1, flags, callback);
if (!ret) {
_findclose(hfile);
return ret;
}
} while (_wfindnext(hfile, &dat) == 0);
_findclose(hfile);
return ret;
}
我传递给函数的最大深度为1。传递-1以搜索所有子目录。下面是一个使用FindFirstFile和FindNextFile的示例,可以递归查找具有给定扩展名的文件
#include "stdafx.h"
#include <Windows.h>
#include <atlpath.h>
#include <list>
#include <iostream>
#ifdef _UNICODE
#define cout wcout
#endif
void FindFiles(
const CString& strRootPath,
const CString& strExt,
std::list<CString>& listFiles,
bool bRecursive = true)
{
CString strFileToFind = strRootPath;
ATLPath::Append(CStrBuf(strFileToFind, MAX_PATH), _T("*.*"));
WIN32_FIND_DATA findData = { 0 };
HANDLE hFileFind = ::FindFirstFile(strFileToFind, &findData);
if (INVALID_HANDLE_VALUE != hFileFind)
{
do
{
CString strFileName = findData.cFileName;
if ((strFileName == _T(".")) || (strFileName == _T("..")))
continue;
CString strFilePath = strRootPath;
ATLPath::Append(CStrBuf(strFilePath, MAX_PATH), strFileName);
if (bRecursive && (ATLPath::IsDirectory(strFilePath)))
{
FindFiles(strFilePath, strExt, listFiles);
}
else
{
CString strFoundExt = ATLPath::FindExtension(strFilePath);
if (! strExt.CompareNoCase(strFoundExt))
istFiles.push_back(strFilePath);
}
} while (::FindNextFile(hFileFind, &findData));
::FindClose(hFileFind);
}
}
int main()
{
std::list<CString> listFiles;
FindFiles(_T("e:\\tests"), _T(".cpp"), listFiles);
for (const auto& strFile : listFiles)
std::cout << strFile.GetString() << std::endl;
return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
#ifdef_UNICODE
#定义coutwcout
#恩迪夫
空心翅片(
常数CString和strRootPath,
const CString&strExt,
std::列表和列表文件,
bool bRecursive=true)
{
CString strFileToFind=strRootPath;
ATLPath::Append(CStrBuf(strFileToFind,MAX_PATH),_T(“*”);
WIN32_FIND_DATA findData={0};
HANDLE hFileFind=::FindFirstFile(strFileToFind,&findData);
if(无效的句柄值!=hFileFind)
{
做
{
CString strFileName=findData.cFileName;
if((strFileName==_T(“.”)| |(strFileName==_T(“…”))
继续;
CString strFilePath=strRootPath;
ATLPath::Append(CStrBuf(strFilePath,MAX_PATH),strFileName);
if(bRecursive&(ATLPath::IsDirectory(strFilePath)))
{
FindFile(strFilePath、strExt、listFiles);
}
其他的
{
CString strFoundExt=ATLPath::FindExtension(strFilePath);
如果(!strExt.CompareNoCase(strFoundExt))
istFiles.push_back(strFilePath);
}
}while(::FindNextFile(hFileFind,&findData));
::FindClose(hFileFind);
}
}
int main()
{
列表文件;
FindFile(_T(“e:\\tests”)、_T(.cpp”)、列表文件);
用于(常量自动&strFile:listFiles)
std::cout下面是一个使用FindFirstFile和FindNextFile的示例,可以递归地查找具有给定扩展名的文件
#include "stdafx.h"
#include <Windows.h>
#include <atlpath.h>
#include <list>
#include <iostream>
#ifdef _UNICODE
#define cout wcout
#endif
void FindFiles(
const CString& strRootPath,
const CString& strExt,
std::list<CString>& listFiles,
bool bRecursive = true)
{
CString strFileToFind = strRootPath;
ATLPath::Append(CStrBuf(strFileToFind, MAX_PATH), _T("*.*"));
WIN32_FIND_DATA findData = { 0 };
HANDLE hFileFind = ::FindFirstFile(strFileToFind, &findData);
if (INVALID_HANDLE_VALUE != hFileFind)
{
do
{
CString strFileName = findData.cFileName;
if ((strFileName == _T(".")) || (strFileName == _T("..")))
continue;
CString strFilePath = strRootPath;
ATLPath::Append(CStrBuf(strFilePath, MAX_PATH), strFileName);
if (bRecursive && (ATLPath::IsDirectory(strFilePath)))
{
FindFiles(strFilePath, strExt, listFiles);
}
else
{
CString strFoundExt = ATLPath::FindExtension(strFilePath);
if (! strExt.CompareNoCase(strFoundExt))
istFiles.push_back(strFilePath);
}
} while (::FindNextFile(hFileFind, &findData));
::FindClose(hFileFind);
}
}
int main()
{
std::list<CString> listFiles;
FindFiles(_T("e:\\tests"), _T(".cpp"), listFiles);
for (const auto& strFile : listFiles)
std::cout << strFile.GetString() << std::endl;
return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
#ifdef_UNICODE
#定义coutwcout
#恩迪夫
空心翅片(
常数CString和strRootPath,
const CString&strExt,
std::列表和列表文件,
bool bRecursive=true)
{
CString strFileToFind=strRootPath;
ATLPath::Append(CStrBuf(strFileToFind,MAX_PATH),_T(“*”);
WIN32_FIND_DATA findData={0};
HANDLE hFileFind=::FindFirstFile(strFileToFind,&findData);
if(无效的句柄值!=hFileFind)
{
做
{
CString strFileName=findData.cFileName;
if((strFileName==_T(“.”)| |(strFileName==_T(“…”))
继续;
CString strFilePath=strRootPath;
ATLPath::Append(CStrBuf(strFilePath,MAX_PATH),strFileName);
if(bRecursive&(ATLPath::IsDirectory(strFilePath)))
{
FindFile(strFilePath、strExt、listFiles);
}
其他的
{
CString strFoundExt=ATLPath::FindExtension(strFilePath);
如果(!strExt.CompareNoCase(strFoundExt))
istFiles.push_back(strFilePath);
}
}while(::FindNextFile(hFileFind,&findData));
::FindClose(hFileFind);
}
}
int main()
{
列表文件;
FindFile(_T(“e:\\tests”)、_T(.cpp”)、列表文件);
用于(常量自动&strFile:listFiles)
文件中的std::cout:“目录或路径以及文件名。文件名可以包括通配符,例如星号(*)或问号(?)是的,我看到了。你想说什么?@richardcrittent这对我没有多大帮助。所以我想没有解决办法?@RichardCrittenI我是说文档说你可以有1(一)个通配符。从文档中可以看到:“目录或路径,以及文件名。文件名可以包括通配符,例如星号(*)或问号(?)“是的,我看到了。你想说什么?@RichardCriten这对我没有多大帮助。所以我想没有办法解决这个问题?@RichardCriten我是说医生说你可以有1(一)通配符。NTFS和Windows API都支持Unicode。您建议的答案不支持。@IInspectable谢谢您的建议!代码已修改为支持Unicode NTFS和Windows API支持Unicode。您建议的答案不支持。@IInspectable谢谢您的建议!代码已修改为支持Unicode