рекурсивный поиск файлов - PullRequest
3 голосов
/ 11 июня 2009

Я пытаюсь выяснить, как решить эту вещь .. По какой-то причине, это заканчивается в определенный момент .. Я не очень хорош в рекурсии, и я уверен, что проблема лежит где-то там ..

Кроме того, даже если я проверил 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 ]

3 голосов
/ 11 июня 2009

Из документации 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 голосов
/ 20 июня 2009

В вашем коде все еще есть несколько ошибок. Попробуйте вместо этого:

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 );
}
2 голосов
/ 11 июня 2009

Вы меняете значение вашей локальной wrkdir переменной:

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

Я думаю, вам нужно позвонить find_files вот так:

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

и не изменять значение wrkdir.

1 голос
/ 14 октября 2011

Рекурсивный поиск файлов с 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 голосов
/ 12 июня 2009

В вашем коде все еще есть ошибки:

  1. вы игнорируете результаты первого поиска. Вы вызываете FindFirstFile и обрабатываете, если это не удается. Но если это удастся, вы не обрабатываете уже извлеченные file_data и перезаписываете его с помощью FindNextFile.
  2. Вы не закрываете дескриптор поиска. Для этого используйте FindClose.
  3. Из вашего существующего кода кажется, что fHandle является глобальным - не должно. Это сломало бы вашу рекурсию.

Также я думаю, что вы можете решить все проблемы в своем коде, уделив больше внимания образцу MSDN, приведенному в документации FindFirstFile.

0 голосов
/ 11 июня 2009

Также ознакомьтесь с реализацией класса CFileFind MFC .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...