c++ Windows API рекурсивный поиск не возвращает ожидаемый каталог



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



    #include "stdafx.h"
#include <iostream>
#include <windows.h> // Microsoft Windows’ main library.
#include <tchar.h> // Needed for _TEXT macro.
#include "Strsafe.h" // Microsoft's library for secure strings.

using namespace std;
typedef wchar_t* LPWSTR, *PWSTR;
int layer = 0;

int recursionFindAbsraction(LPWSTR Dir, LPWSTR FilNam, LPWSTR filePath);
//original directory, new directory with *.* attached
//new directory with entire directory, new entire directory with *.* attached
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t holder[MAX_PATH];//using this instead of string
wchar_t direct[MAX_PATH];
wchar_t filePath[MAX_PATH];

wcout << "Please enter the directory you wish to search: " << endl;
wcin >> direct;
wcout << direct << endl;


wcout << "Please enter the filename (program will automatically seach for all files like it): " << endl;
wcin >> holder;
wcout << holder << endl;

recursionFindAbsraction(direct, holder, filePath);
getchar();
getchar();
return 0;

}

int recursionFindAbsraction(LPWSTR Dir, LPWSTR FilNam, LPWSTR filePath){
WIN32_FIND_DATAW ptrFileData;
HANDLE hFile = NULL;
BOOL bGetNext = true;

wchar_t newDir[MAX_PATH];
wchar_t newDir2[MAX_PATH];
wchar_t filePathHolder[MAX_PATH];

//add slash then put directory into new variable, newDir
StringCchCatW(Dir, MAX_PATH, _TEXT("\"));

//Here, we split the path to avoid appending *.* to the current directory
StringCchCopyW(filePathHolder, MAX_PATH, Dir);
StringCchCopyW(newDir, MAX_PATH, Dir);
StringCchCopyW(newDir2, MAX_PATH, Dir);
StringCchCatW(newDir2, MAX_PATH, _TEXT("*.*"));
hFile = FindFirstFile(newDir2, &ptrFileData);

if (hFile == INVALID_HANDLE_VALUE)
{
printf("FindFirstFile failed (%d)n", GetLastError());
getchar();
//return 0;
}

while (bGetNext){

if ((ptrFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0)
{
int setLoop = (ptrFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
wcout << " file Attribute bitwise: " << setLoop;
wcout << "file hidden " << endl;
int counter = 0; counter++;
wcout << "counter: " << counter << endl;
wcout << "string compare: " << _wcsicmp(ptrFileData.cFileName, _TEXT("..")) << endl;
wcout << "filename: " << ptrFileData.cFileName << endl;
Sleep(100);
/*
if (_wcsicmp(ptrFileData.cFileName, _TEXT(".")) == 0){
wcout << "Breaking1. " << endl;
continue;
}
if (_wcsicmp(ptrFileData.cFileName, _TEXT("..")) == 0){
wcout << "Breaking2. " << endl;
continue;
}*/
}

else
{
if (_wcsicmp(ptrFileData.cFileName, FilNam) == 0){
wcout << "The first file found is: " << ptrFileData.cFileName << endl;
//_tprintf(TEXT("The first file found is %sn"), ptrFileData.cFileName);
FindClose(hFile);
//getchar();
break;
}
if ((((ptrFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)) && ((ptrFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0))
{//must check to see if folder
layer++;
wcout << "Layer: " << layer << endl;
ptrFileData.cFileName;
//when this gets called because it's a folder, the name
//gets added to the wrong directory
StringCchCatW(newDir, MAX_PATH, ptrFileData.cFileName);
wcout << " newDir/fulldir: " << newDir<< endl;
//resolves full path name at this point
wcout << "filePathHolder from last else: " << filePathHolder << endl;
wcout << "filename: " << ptrFileData.cFileName << endl;

recursionFindAbsraction(newDir, FilNam, filePath);

}

}
wcout << "&ptrFileData: " << &ptrFileData << endl;
wcout << "hFile: " << hFile << endl;
bGetNext = FindNextFile(hFile, &ptrFileData);
wcout << " exit: " << bGetNext<< endl;
}
FindClose(hFile);
return 0;
}
573   1  

1 ответ:

Вот простой пример рекурсивного поиска. Обратите внимание, что он использует do{...}while(...); , что облегчает переход к концу цикла

void findfile_recursive(const std::wstring &folder, const std::wstring &filename, std::vector<std::wstring> &files)
{
    std::wstring wildcard = folder + L"\\*";
    WIN32_FIND_DATA fd;
    HANDLE handle = FindFirstFile(wildcard.c_str(), &fd);
    if (handle == INVALID_HANDLE_VALUE)
        return;
    do
    {
        if (wcscmp(fd.cFileName, L".") == 0 || wcscmp(fd.cFileName, L"..") == 0)
            continue;
        std::wstring path = folder + L"\\" + std::wstring(fd.cFileName);

        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            findfile_recursive(path, filename, files);
        else if (_wcsicmp(fd.cFileName, filename.c_str()) == 0)
            files.push_back(path);

    } while (FindNextFile(handle, &fd));
    FindClose(handle);
}

int _tmain(int, wchar_t*[])
{
    std::vector<std::wstring> files;
    findfile_recursive(L"c:\\test", L"file.txt", files);
    for (auto file : files)
        std::wcout << file << endl;
}

Вы можете изменить свою функцию, чтобы использовать do/while. При рекурсивном вызове функции убедитесь, что она имеет правильный аргумент. newDir изменения в цикле, вы не можете использовать его в качестве ссылки. Вместо этого используйте Dir.

int recursionFindAbsraction(LPWSTR Dir, LPWSTR FilNam, LPWSTR filePath)
{
    ...
    //while (bGetNext)***
    do
    {
        if (wcscmp(ptrFileData.cFileName, L".") == 0 || wcscmp(ptrFileData.cFileName, L"..") == 0)
            continue;

        if (ptrFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
            continue;//***skip hidden files and directories

        if (ptrFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            //***wrong redirection:
            //StringCchCatW(newDir, MAX_PATH, ptrFileData.cFileName);

            //***change to:
            StringCchCopyW(newDir, MAX_PATH, Dir);
            StringCchCatW(newDir, MAX_PATH, ptrFileData.cFileName);
            recursionFindAbsraction(newDir, FilNam, filePath);
        }
        else if (_wcsicmp(ptrFileData.cFileName, FilNam) == 0)
        {
            std::wcout << "The first file found is: " << Dir << ptrFileData.cFileName << endl;
        }

    } while (FindNextFile(hFile, &ptrFileData));//***

    FindClose(hFile);
    return 0;
}

Comments

    Ничего не найдено.