c ++ - rekursiv filsøgning

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at finde ud af, hvordan man arbejder denne ting ud. Af en eller anden grund slutter det på et bestemt tidspunkt. Jeg er ikke særlig god på rekursion, og jeg er sikker på, at problemet ligger et sted der ..


Også selvom jeg kontrollerede for cFileName!='..', vises det stadig i slutningen, ikke sikker på hvorfor men '.' vises ikke mere ..


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


Efter at have ændret dem, tæller programmet ikke de resterende filer tilbage.


For eksempel, hvis der er en undermappe, der hedder test, opregner den alt inde i testen, men slutter ikke at optage filerne inde i den angivne originale mappe.

Bedste reference


Fra FindFirstFile-dokumentationen: [12]



  Hvis funktionen mislykkes eller ikke
  Find filer fra søgestrengen i
  Parameteren lpFileName, afkastet
  værdien er INVALID\_HANDLE\_VALUE og
  indholdet af lpFindFileData er
  ubestemt.



Du bør kun afslutte den ene iteration ikke hele programmet:


   if( fHandle == INVALID\_HANDLE\_VALUE )
   {
     return;
   }


Og dette kan løse dit andet problem:


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


Se også @fretjes svar også. Det giver et andet problem, som din kode har.


Opdateret nyt: Du skal også bruge fHandle som en lokal variabel, ikke global variabel.


Skifte til:


 HANDLE fHandle = FindFirstFile( temp.c\_str(), &file\_data );

Andre referencer 1


Du ændrer værdien af ​​din lokale wrkdir -variabel:


wrkdir = wrkdir + L"\" + file\_data.cFileName;
find\_files( wrkdir );


Jeg tror, ​​du skal ringe find\_files der sådan:


find\_files( wrkdir + L"\" + file\_data.cFileName );


og ikke ændre værdien af ​​wrkdir.

Andre referencer 2


Der er stadig flere fejl i din kode. Prøv det her i stedet:


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

Andre referencer 3


Rekursiv filsøgning med 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;
    }

Andre referencer 4


Se også udførelsen af ​​CFileFind MFC-klassen. [13]

Andre referencer 5


Du har stadig fejl i din kode:



  1. Du ignorerer resultaterne af den første søgning. du ringer FindFirstFile og håndterer, hvis det fejler. Men hvis det lykkes, behandler du ikke allerede hentet file\_data og overskriver det med FindNextFile.

  2. Du må ikke lukke søgehåndtaget. Brug FindClose til det.

  3. Fra din eksisterende kode ser det ud til, at fHandle er global - det burde ikke være det. Det ville bryde din rekursion.



Jeg tror også, at du kan løse alle problemer i din kode ved at være mere opmærksom på MSDN-prøven, der findes i FindFirstFile-dokumentationen.