2015-10-20 89 views
2

我目前正在嘗試編寫一個程序,遞歸搜索使用Windows.h中存在的實用程序的文件。當我執行下面的代碼時,文件路徑不斷被添加到搜索的最後一個文件路徑中,但文件夾不被搜索,並且句柄沒有被標記爲無效。我已經燉了幾天。爲什麼這不是遞歸搜索? 編輯:更正了使用按位比較的代碼。發生同樣的錯誤。C++ Windows API遞歸搜索沒有返回預期的目錄

#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 %s\n"), 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; 
} 
+2

'FindFirstFile'總是返回條目'.'和'先天下之憂..',所以你的測試'如果(_wcsicmp(ptrFileData.cFileName,_TEXT( 「」))== 0)'會導致你立即跳出循環。 –

+2

您可能還想使用'&'而不是'=='來測試屬性,因爲一次設置多個屬性標誌是很常見的。 –

+0

我沒有使用'WIN32_FIND_DATAW'結構/類,但是我確信你不應該直接比較'.dwFileAttributes'屬性和'FILE_ATTRIBUTE_DIRECTORY',因爲你不應該和' FILE_ATTRIBUTE_HIDDEN'直接。我敢打賭,這些是dwFileAttributes位域(或int)中的標誌,並且您應該檢查每個位是否在dwFileAttributes字段中啓用。像'((ptrFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!= 0)&&((ptrFileData.dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)== 0)'但更好的,如果你檢查更多的信息.​​.. – Ryu

回答

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

結束時,你可以改變你的函數的使用做/時。當遞歸調用函數時,確保它有正確的參數。 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; 
} 
+0

是的!從邏輯上講,這就是我想要做的事情,但我在控制語句中迷失了方向。謝謝! – nattylightfortheladies