使用FindFirstFile和FindNextFile C++进行递归硬盘搜索

Recursive hard disk search with FindFirstFile & FindNextFile C++

本文关键字:递归 硬盘 搜索 C++ FindFirstFile FindNextFile 使用      更新时间:2023-10-16

我没有发现哪里出了问题。此当前代码直接跳到关闭文件。没有处理任何文件,我可能只是错过了一些明显的东西,这是漫长的一天。

我的功能是在硬盘(c:(上搜索给定的文件。例如.txt。&这里的strFilePath将在FindFirstFile声明中使用。

请提供任何帮助。

谢谢。

String Copy::SearchDrive( const String& strFile, const String& strFilePath, const bool& bRecursive, const bool& bStopWhenFound ) const
{
    HANDLE hFile;
    WIN32_FIND_DATA file;
    hFile = FindFirstFile("C:\", &file);
    String strFoundFilePath = "";
    if ( hFile )
    {
        while ( FindNextFile( hFile, &file))
        {
            String strTheNameOfTheFile = file.cFileName;
            // It could be a directory we are looking at
            // if so look into that dir
            if ( file.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY
                && bRecursive )
            {
                String strNewFilePath = strFilePath + "\";
                strNewFilePath += strTheNameOfTheFile;
                SearchDrive( strFile, strNewFilePath, bRecursive, bStopWhenFound );
            }
            else
            {
                if ( strTheNameOfTheFile == strFile )
                {
                    strFoundFilePath = strFilePath;
                    strFoundFilePath += "\";
                    strFoundFilePath += strFile;
                    /// TODO
                    // ADD TO COLLECTION TYPE
                    if ( bStopWhenFound )
                    {
                        break;
                    }
                }
            }
        }
        CloseHandle( hFile );
    }
    return strFoundFilePath;
}

您的代码中有很多逻辑错误。试试这个(你没有指出你使用的是哪个编译器,所以我假设C++Builder,它有一个大写的S String类。如果你使用不同的编译器,可以根据需要调整代码(:

String Copy::SearchDrive(const String& strFile, const String& strFilePath, const bool& bRecursive, const bool& bStopWhenFound) const
{
    String strFoundFilePath;
    WIN32_FIND_DATA file;
    String strPathToSearch = strFilePath;
    if (!strPathToSearch.IsEmpty())
        strPathToSearch = IncludeTrailingPathDelimiter(strPathToSearch);
    HANDLE hFile = FindFirstFile((strPathToSearch + "*").c_str(), &file);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        do
        {
            String strTheNameOfTheFile = file.cFileName;
            // It could be a directory we are looking at
            // if so look into that dir
            if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                if ((strTheNameOfTheFile != ".") && (strTheNameOfTheFile != "..") && (bRecursive))
                {
                    strFoundFilePath = SearchDrive(strFile, strPathToSearch + strTheNameOfTheFile, bRecursive, bStopWhenFound);
                    if (!strFoundFilePath.IsEmpty() && bStopWhenFound)
                        break;
                }
            }
            else
            {
                if (strTheNameOfTheFile == strFile)
                {
                    strFoundFilePath = strPathToSearch + strFile;
                    /// TODO
                    // ADD TO COLLECTION TYPE
                    if (bStopWhenFound)
                        break;
                }
            }
        }
        while (FindNextFile(hFile, &file));
        FindClose(hFile);
    }
    return strFoundFilePath;
}

String strFoundFilePath = SearchDrive("file.ext", "C:\", ...);

UPDATE:SearchDrive()的一种替代实现,在子目录中递归时不保持多个搜索句柄打开:

#include <memory>
String Copy::SearchDrive(const String& strFile, const String& strFilePath, const bool& bRecursive, const bool& bStopWhenFound) const
{
    String strFoundFilePath;
    WIN32_FIND_DATA file;
    String strPathToSearch = strFilePath;
    if (!strPathToSearch.IsEmpty())
        strPathToSearch = IncludeTrailingPathDelimiter(strPathToSearch);
    HANDLE hFile = FindFirstFile((strPathToSearch + "*").c_str(), &file);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        std::auto_ptr<TStringList> subDirs;
        do
        {
            String strTheNameOfTheFile = file.cFileName;
            // It could be a directory we are looking at
            // if so look into that dir
            if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                if ((strTheNameOfTheFile != ".") && (strTheNameOfTheFile != "..") && (bRecursive))
                {
                    if (subDirs.get() == NULL)
                        subDirs.reset(new TStringList);
                    subDirs->Add(strPathToSearch + strTheNameOfTheFile);
                }
            }
            else
            {
                if (strTheNameOfTheFile == strFile)
                {
                    strFoundFilePath = strPathToSearch + strFile;
                    /// TODO
                    // ADD TO COLLECTION TYPE
                    if (bStopWhenFound)
                        break;
                }
            }
        }
        while (FindNextFile(hFile, &file));
        FindClose(hFile);
        if (!strFoundFilePath.IsEmpty() && bStopWhenFound)
            return strFoundFilePath;
        if (subDirs.get() != NULL)
        {
            for (int i = 0; i < subDirs->Count; ++i)
            {
                strFoundFilePath = SearchDrive(strFile, subDirs->Strings[i], bRecursive, bStopWhenFound);
                if (!strFoundFilePath.IsEmpty() && bStopWhenFound)
                    break;
            }
        }
    }
    return strFoundFilePath;
}

您的条件不正确,您应该将其与INVALID_HANDLE_VALUE 进行比较

 if ( hFile != INVALID_HANDLE_VALUE)

除了跳过FindFirstFile返回的第一个匹配文件之外,这是你想要的吗?

此外,我相信你需要一个通配符c:\*,否则它将只匹配c:\本身

hFile = FindFirstFile("C:\*", &file);