2015-10-20 90 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