递归文件搜索

时间:2009-06-10 23:35:23

标签: c++ windows winapi recursion

我正在试图弄清楚如何解决这个问题......出于某种原因,它在某个时刻结束了......我不太擅长递归,我确信问题出在某处......

另外,即使我检查了cFileName!=“..”,它仍然显示在最后,不知道为什么而是“。”不再显示..

void find_files( wstring wrkdir )
{
    wstring temp;

    temp = wrkdir + L"\\" + L"*"; 
    fHandle = FindFirstFile( temp.c_str(), &file_data );

    if( fHandle == INVALID_HANDLE_VALUE )
    {
         return;
    }
    else 
    { 
        while( FindNextFile( fHandle, &file_data ) ) 
        {
            if( file_data.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY &&
                wcscmp(file_data.cFileName, L".") != 0 && 
                        wcscmp(file_data.cFileName, L"..") != 0 )
            {
                find_files( wrkdir + L"\\" + file_data.cFileName  );
            }
            else if( file_data.dwFileAttributes != FILE_ATTRIBUTE_HIDDEN && 
                 file_data.dwFileAttributes != FILE_ATTRIBUTE_SYSTEM  )
            {
                results << wrkdir << "\\" << file_data.cFileName << endl;
            }
        }
    }
}

更改后,程序不会枚举剩下的剩余文件..

例如,如果有一个名为test的子文件夹,它会枚举test中的所有内容,但不会完成枚举指定原始目录中的文件。

6 个答案:

答案 0 :(得分:3)

来自FindFirstFile文档:

  

如果功能失败或失败   从中搜索字符串中的文件   lpFileName参数,返回   值为INVALID_HANDLE_VALUE和   lpFindFileData的内容是   不确定的。

你应该只退出一次迭代而不是退出整个程序:

   if( fHandle == INVALID_HANDLE_VALUE )
   {
     return;
   }

这可能会解决您的其他问题:

else if( file_data.dwFileAttributes != FILE_ATTRIBUTE_HIDDEN && 
   file_data.dwFileAttributes != FILE_ATTRIBUTE_SYSTEM  &&
   wcscmp(file_data.cFileName, L".") != 0 && 
   wcscmp(file_data.cFileName, L"..") != 0
 )
{
    results << wrkdir << "\\" << file_data.cFileName << endl;
}

另见@ fretje的回答。它给你的代码带来了另一个问题。

更新了新内容:您还需要将fHandle用作局部变量,而不是全局变量。

更改为:

 HANDLE fHandle = FindFirstFile( temp.c_str(), &file_data );

答案 1 :(得分:2)

您正在更改本地wrkdir变量的值:

wrkdir = wrkdir + L"\\" + file_data.cFileName;
find_files( wrkdir );

我认为你必须像这样打电话给find_files

find_files( wrkdir + L"\\" + file_data.cFileName );

并且不会更改wrkdir的值。

答案 2 :(得分:2)

您的代码中仍有几个错误。试试这个:

void find_files( wstring wrkdir )
{
    wstring wrkdirtemp = wrkdir;
    if( !wrkdirtemp.empty() && (wrkdirtemp[wrkdirtemp.length()-1] != L'\\')  )
    {
      wrkdirtemp += L"\\";
    }

    WIN32_FIND_DATA file_data = {0};
    HANDLE hFile = FindFirstFile( (wrkdirtemp + L"*").c_str(), &file_data );

    if( hFile == INVALID_HANDLE_VALUE )
    {
         return;
    }

    do
    {
        if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
        {
            if( (wcscmp(file_data.cFileName, L".") != 0) && 
                (wcscmp(file_data.cFileName, L"..") != 0) )
            {
                find_files( wrkdirtemp + file_data.cFileName );
            }
        }
        else
        {
            if( (file_data.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) == 0 )
            {
                results << wrkdirtemp << file_data.cFileName << endl;
            }
        }
    }
    while( FindNextFile( hFile, &file_data );

    FindClose( hFile );
}

答案 3 :(得分:1)

使用dirent.h进行递归文件搜索

#include <iostream>
#include <dirent.h>
#include <string.h>    

bool isUpDirecory(const char* directory) {
        if (strcmp(directory, "..") == 0 || strcmp(directory, ".") == 0)
            return true;
        else
            return false;
    }

    bool findFile(const std::string& fileName, const std::string& path,
            std::string& resultPath) {
        dirent* entry;
        DIR* dir = opendir(path.c_str());

        if (dir == NULL)
            return false;

        while ((entry = readdir(dir)) != NULL) {
            if (entry->d_type == DT_REG) {
                if (fileName.compare(entry->d_name) == 0) {
                    resultPath = path + "/" + entry->d_name;
                    closedir(dir);
                    return true;
                }
            }
        }

        rewinddir(dir);

        while ((entry = readdir(dir)) != NULL) {
            if (entry->d_type == DT_DIR) {
                if (!isUpDirecory(entry->d_name)) {
                    std::string nextDirectoryPath = path + "/" + entry->d_name;
                    bool result = findFile(fileName, nextDirectoryPath, resultPath);
                    if (result == true) {
                        closedir(dir);
                        return true;
                    }
                }
            }
        }

        closedir(dir);
        return false;
    }

    int main() {
        std::string path;
        bool result = findFile("text.txt", "/home/lamerman/", path);
        std::cout << path << std::endl;
        return 0;
    }

答案 4 :(得分:0)

另外,请查看CFileFind MFC类的实现。

答案 5 :(得分:-1)

您的代码中仍然存在错误:

  1. 您忽略了第一次搜索的结果。你调用FindFirstFile并处理它是否失败。但如果成功,则不要处理已经获取的file_data并使用FindNextFile覆盖它。
  2. 您不会关闭搜索句柄。使用FindClose。
  3. 从你现有的代码来看,似乎fHandle是全局的 - 它不应该。它会打破你的递归。
  4. 此外,我认为您可以通过更多关注FindFirstFile文档中提供的MSDN示例来解决代码中的所有问题。