递归文件搜索

3

我正在尝试弄清楚如何解决这个问题...出现某些原因,它在某个特定点结束...我不太擅长递归,但我确定问题出在那里的某个地方...

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

你能详细说明出了什么问题吗? - Lucas B
6个回答

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

由于某些原因,仍然无法工作...我已经苦思冥想了几个小时了...顺便说一下,我编辑了原帖。 - Charles Khunt
更新了一个我看到的新问题。 - Brian R. Bondy

2
你正在修改本地变量 wrkdir 的值:
wrkdir = wrkdir + L"\\" + file_data.cFileName;
find_files( wrkdir );

我认为您需要这样调用find_files函数:

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

并且不改变wrkdir的值。


2

你的代码仍然存在几个bug。尝试使用以下代码:

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

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

0

-1

你的代码仍然存在错误:

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

此外,我认为你可以通过更加关注FindFirstFile文档中提供的MSDN示例来解决你代码中的所有问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接