Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用FindFirstFile和FindNextFile递归查找具有特定扩展名的文件_C++_Windows_Winapi_Recursion_Wildcard - Fatal编程技术网

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以搜索所有子目录。

下面是一个使用FindFirstFileFindNextFile的示例,可以递归查找具有给定扩展名的文件

#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下面是一个使用FindFirstFileFindNextFile的示例,可以递归地查找具有给定扩展名的文件

#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