【问题标题】:recursive file search递归文件搜索
【发布时间】:2009-06-10 23:35:23
【问题描述】:

我正试图弄清楚如何解决这个问题..由于某种原因,它在某个点结束..我不太擅长递归,我确定问题出在某个地方..

另外,即使我检查了 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 中的所有内容,但不会枚举完指定原始目录中的文件。

【问题讨论】:

  • 您能详细说明问题所在吗?

标签: c++ windows winapi recursion


【解决方案1】:

来自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 );

【讨论】:

  • 由于某种原因,仍然无法正常工作.. 已经挠头好几个小时了.. 我编辑了原帖顺便说一句
  • 更新了我看到的一个新问题
【解决方案2】:

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

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

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

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

并且不改变wrkdir的值。

【讨论】:

    【解决方案3】:

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

    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 );
    }
    

    【讨论】:

      【解决方案4】:

      使用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;
          }
      

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          您的代码中仍有错误:

          1. 您忽略了第一次搜索的结果。如果失败,您调用 FindFirstFile 并处理。但如果它成功了,你就不用处理已经获取的 file_data 并用 FindNextFile 覆盖它。
          2. 您没有关闭搜索句柄。为此使用 FindClose。
          3. 从您现有的代码看来,fHandle 似乎是全局的 - 它不应该。它会破坏你的递归。

          另外我认为您可以通过更多地关注 FindFirstFile 文档中提供的 MSDN 示例来解决代码中的所有问题。

          【讨论】:

            猜你喜欢
            • 2010-12-24
            • 2012-06-15
            • 1970-01-01
            • 2020-02-24
            • 2014-12-09
            • 2021-01-25
            • 1970-01-01
            • 1970-01-01
            • 2013-07-13
            相关资源
            最近更新 更多