2017-10-11 42 views
1

你好,我是新手。經過漫長的絕望搜索,我想發佈這個問題:如何獲得具有特定擴展名的驅動器中的所有文件的列表?

我正在開發一個C++程序,遞歸遍歷所有搜索特定文件類型的文件夾和子文件夾。

首先功能FindFiles(string, string, bool)工作像一個魅力,但它的第二種形式FindFiles(struct var)不能正常工作:它不會遍歷所有文件夾和子文件夾。

事實上,我需要第二種形式,因爲由於搜索可能太長,我需要使用API​​ CreateThread創建線程,並將我的arguments struct作爲LPVOID傳遞給它。

#include <windows.h> 
#include <string> 
#include <iostream> 
using namespace std; 



// Arguments struct 
struct args{ 
    string strDir; 
    string strFilter; 
    bool bRecurse; 
}; 


void FindFiles(string strDir, string strFilter, bool bRecurse); 
void FindFiles(args); 


int main(){ 

// FindFiles("D:", "*.mp3", true); // works fine 

    args ar; 
    ar.bRecurse = true; 
    ar.strDir = "D:"; 
    ar.strFilter = "*.mp3"; 

    FindFiles(ar); // doesn't work fine 

    cout << endl; 
    return 0; 
} 

void FindFiles(string strDir, string strFilter, bool bRecurse = true){ 
    if(bRecurse) 
     FindFiles(strDir, strFilter, false); 
    strDir += "\\"; 
    WIN32_FIND_DATA wfd; 

    string strFileFilter = strDir + (bRecurse ? "*" : strFilter); 
    HANDLE hFile = FindFirstFile(strFileFilter.c_str(), &wfd); 

    if(INVALID_HANDLE_VALUE == hFile) 
     return; 
    else{ 
     if(!bRecurse) 
      cout << strDir + string(wfd.cFileName) << endl; 
     while(FindNextFile(hFile, &wfd)){ 
      if(!bRecurse) 
       cout << strDir + string(wfd.cFileName) << endl; 
      else{ 
       if((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0 && 
        wfd.cFileName[0] != '.') 
        FindFiles(strDir + string(wfd.cFileName), strFilter, true); 
      } 
     } 
    // FindClose(hFile); 
    } 
} 

void FindFiles(args ar){ 
    if(ar.bRecurse){ 
     ar.bRecurse = false; 
     FindFiles(ar); 
    } 
    ar.strDir += "\\"; 
    WIN32_FIND_DATA wfd; 

    string strFileFilter = ar.strDir + (ar.bRecurse ? "*" : ar.strFilter); 
    HANDLE hFile = FindFirstFile(strFileFilter.c_str(), &wfd); 

    if(INVALID_HANDLE_VALUE == hFile) 
     return; 
    else{ 
     if(!ar.bRecurse) 
      cout << ar.strDir + string(wfd.cFileName) << endl; 
     while(FindNextFile(hFile, &wfd)){ 
      if(!ar.bRecurse) 
       cout << ar.strDir + string(wfd.cFileName) << endl; 
      else{ 
       if((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0 && 
        wfd.cFileName[0] != '.'){ 
         ar.strDir += string(wfd.cFileName); 
         ar.bRecurse = true; 
         FindFiles(ar); 
       } 
      } 
     } 
     FindClose(hFile); 
    } 
} 

請看看第二個表格,因爲它是我的。我認爲那裏有一些愚蠢的錯誤。

任何幫助我真的很感激它。

+0

@RemyLebeau:其實第一種形式,我發現它的地方在互聯網上,從而可以看到我編輯它作爲第二種形式。但是,如果你建議我一些替代品,那麼我真的很感激它。感謝名單! – WonFeiHong

+0

你正在嘗試*方式*太難。使用[recursive_directory_iterator](https://docs.microsoft.com/en-us/cpp/standard-library/recursive-directory-iterator-class)爲您完成這項工作。此外,在本地使用Unicode的文件系統上對文件名使用ANSI/MBCS編碼是一個錯誤。 – IInspectable

+0

@IInspectable:可以解釋更多關於錯誤的信息。 Thanx爲有用的鏈接。 – WonFeiHong

回答

4

你的FindFiles() 1 PARAM版本不遞歸,因爲它修改ar.bRecurse標誌,因此搜索子文件夾時總是假的:

void FindFiles(args ar){ 
    if(ar.bRecurse){ 
     ar.bRecurse = false; // <-- modified! 
     FindFiles(ar); 
    } 
    ... 
    // ar.bRecurse is still false here! 
} 

FindFiles()三PARAMS版本不做到這一點:

void FindFiles(string strDir, string strFilter, bool bRecurse = true){ 
    if(bRecurse) 
     FindFiles(strDir, strFilter, false); // <-- bRecurse is not modified here! 
    ... 
    // bRecurse is still the original value here! 
} 

最簡單的辦法是,初始FindFiles()通話後重置ar.bRecurse回真:

void FindFiles(args ar){ 
    if(ar.bRecurse){ 
     ar.bRecurse = false; // <-- modified! 
     FindFiles(ar); 
     ar.bRecurse = true; // <-- reset here! 
    } 
    ... 
} 

或使用該調用一個臨時的結構:

void FindFiles(args ar){ 
    if(ar.bRecurse){ 
     args arTmp = ar; // <-- temp copy! 
     arTmp.bRecurse = false; // <-- modify the copy! 
     FindFiles(arTmp); 
    } 
    ... 
    // ar.bRecurse is still the original value here! 
} 

現在,這麼說,你並不真的需要在功能上,在所有bRecurse檢查。它實際上只是在輸入文件夾中掃描匹配的文件,然後再次掃描該文件夾才能找到子文件夾。您可以通過使用一個單一的搜索和本地緩存的子文件夾旁邊的搜索,完成同樣的邏輯如:

#include <windows.h> 

#include <string> 
#include <iostream> 
#include <vector> 

using namespace std; 

// Arguments struct 
struct args 
{ 
    string strDir; 
    string strExt; 
    bool bRecurse; 
}; 

void FindFiles(const string &strDir, const string &strExt, bool bRecurse = true); 
void FindFiles(const args &ar); 

int main() 
{  
    // FindFiles("D:", ".mp3", true); 

    args ar; 
    ar.strDir = "D:"; 
    ar.strExt = ".mp3"; 
    ar.bRecurse = true; 

    FindFiles(ar); 

    cout << endl; 
    return 0; 
} 

void FindFiles(const string &strDir, const string &strExt, bool bRecurse) 
{ 
    string strSearchDir = strDir; 
    vector<string> vDirs; 

    if (!strSearchDir.empty()) 
    { 
     switch (strSearchDir[strSearchDir.size()-1]) 
     { 
      case '\\': 
      case '/': 
       break; 
      default: 
       strSearchDir += "\\"; 
       break; 
     } 
    } 

    WIN32_FIND_DATAA wfd = {}; 

    HANDLE hFile = FindFirstFileA((strSearchDir + "*.*").c_str(), &wfd); 
    if (INVALID_HANDLE_VALUE == hFile) 
     return; 

    do 
    { 
     string strFilename(wfd.cFileName); 

     if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
     { 
      if ((strFilename == ".") || (strFilename == "..")) 
       continue; 

      if (bRecurse) 
       vDirs.push_back(strSearchDir + strFilename); 
     } 
     else 
     { 
      if (!strExt.empty()) 
      { 
       if (strFilename.size() < strExt.size()) 
        continue; 

       if (CompareStringA(LOCALE_USER_DEFAULT, NORM_IGNORECASE, strFilename.c_str()+(strFilename.size()-strExt.size()), strExt.size(), strExt.c_str(), strExt.size()) != 2) 
        continue; 
      } 

      cout << strSearchDir << strFilename << endl; 
     } 
    } 
    while (FindNextFile(hFile, &wfd)); 

    FindClose(hFile); 

    if (bRecurse) 
    { 
     for(vector<string>::iterator iter = vDirs.begin(), end = vDirs.end(); iter != end; ++iter) 
      FindFiles(*iter, strExt, true); 
    } 
} 

void FindFiles(const args &ar) 
{ 
    FindFiles(ar.strDir, ar.strExt, ar.bRecurse); 
} 
+0

非常感謝。我嘗試過它,它的功能就像一個魅力。你太有建設性。明天我會檢查你的整個代碼,現在我太困了。 – WonFeiHong

+0

對不起,我沒有足夠的分數投票。 – WonFeiHong

+0

是的,真的是這個問題當我修改'ar.bRecurse'時,它在子文件夾中總是爲false。但我不明白爲什麼? – WonFeiHong

相關問題