2015-12-23 70 views
0

我想寫一個腳本來遞歸地掃描一個磁盤並返回目錄,文件的總數並且還顯示找到的最大文件。 我知道有很多信息可以在StackOverflow或網絡上找到,但我發現的所有示例似乎都存在與真正掃描磁盤有關的問題。 下面的腳本使用FindFile和FindNextFile函數來掃描文件。如果文件屬性返回,該函數找到一個目錄,它會將該名稱寫入一個列表中,稍後再進行搜索。在搜索完當前目錄之後,腳本將列表中的第一項(即要掃描的目錄)從列表中移除,並掃描此目錄。遞歸文件搜索的問題

我的問題是,掃描幾百目錄和子目錄節目結束一個錯誤

Unhandled exception at ..... (ntdll.dll) in File Lister 6.0.exe: .....: Stack overflow 

Unhandled exception at ..... (ntdll.dll) in File Lister 6.0.exe: ......: Access violation writing location 0x00f30fe8. 

但當時的掃描目錄後是絕不相同。

我一直在試圖解決這個問題,但找不到明確的理由。 因此,我非常感謝,如果有人可以幫助

以下是我的代碼。我知道它看起來非常的新手,我的道歉是

#include <windows.h> 
    #include <iostream> 
    #include <fstream> 
    #include <conio.h> 
    #include <ctype.h> 
    #include <string> 
    #include <string.h> 
    #include <stdio.h> 
    #include <direct.h> 
    #include <list> 

    using namespace std; 


    list <string> myList; 
    std::list<string>::iterator it; 

     int siZe; 
     int siZekB; 
     bool bSearchSubdirectories=true; 
     HANDLE handle; 
     LPCTSTR strPattern; 
     std::string temp; 
     std::string temp1; 
     std::string temp2; 
     std::string temp3; 
     WIN32_FIND_DATA search_data; 
     int DIRPlace; 
     int MaxDir=400000000; 

     int telDIR=1; 
     int telFILES=1; 
     double LargestFile=0; 
     string LargestFileName; 
     string SDir; 


    std::string string_to_hex(const std::string& input) 
    { 
     static const char* const lut = "ABCDEF"; 
     size_t len = input.length(); 

     std::string output; 
     output.reserve(2 * len); 
     for (size_t i = 0; i < len; ++i) 
     { 
      const unsigned char c = input[i]; 
      output.push_back(lut[c >> 4]); 
      output.push_back(lut[c & 15]); 
     } 
     return output; 
    } 



    int SearchDirectory(string FileSearch ,string refvecFiles, 
         bool bSearchSubdirectories) 
    { 

     WIN32_FIND_DATA search_data; 
     memset(&search_data, 0, sizeof(WIN32_FIND_DATA)); 
     HANDLE handle = FindFirstFile((refvecFiles+FileSearch).c_str(), &search_data); 
     temp = refvecFiles; 
     while(handle != INVALID_HANDLE_VALUE) { 

       do{ 
        if (search_data.cFileName[0]!='.'){ 
          temp2=search_data.dwFileAttributes; 
          temp3=string_to_hex(temp2); 
          DIRPlace=strlen(temp3.c_str())-1; 
         switch (temp3[DIRPlace-1]) 
         { 
          case '1': //Directory 
           temp = refvecFiles; 
           temp1=search_data.cFileName; 
           temp2=search_data.dwFileAttributes; 
           myList.push_back(temp+temp1); 
           telDIR++; 
           break; 
         default: //Other types (Files etc) 
           siZe=(search_data.nFileSizeHigh * (MAXDWORD+1)) + search_data.nFileSizeLow; 
           siZekB=((search_data.nFileSizeHigh * (MAXDWORD+1)) + search_data.nFileSizeLow)/1024; 
           temp = refvecFiles; 
           temp1=search_data.cFileName; 
           temp2=search_data.dwFileAttributes; 
           if (siZekB>LargestFile){ 
            LargestFile=siZekB; 
            LargestFileName=temp.substr(0, temp.size()) + "\\" + temp1; 
           } 
           telFILES++; 
           break; 
         } 
        } 
       }while  (FindNextFile(handle, &search_data) != FALSE && telDIR<MaxDir); 
            string line,SearD, LineFiller,FrontString, BackString; 


         it=myList.begin(); 
         SearD=*it+"\\\\"; 
         myList.remove(*it); 
         if (SearD.length()>60) 
         { 
          FrontString=SearD.substr(0,10); 
          BackString=SearD.substr(SearD.length()-44); 
          LineFiller="......"; 
          FrontString=FrontString+LineFiller+BackString; 
         }else{ 
         FrontString=SearD; 
         } 
         cout<<"Exploring:                "<<"\r"; 
         cout<<"Exploring: "<<FrontString<<"\r\r"; 
         SearchDirectory("\\*",SearD, false);  
     } 
     FindClose(handle); 
     return 0; 

    } 





    int main(int argc, char* argv[]) 
    { 
     std::cout<< "Enter directory to be searched: "; 
     getline(cin,SDir); 
     std::cout<< "\n"; 
     try{ 
     SearchDirectory("\\*",SDir, false); 
     }catch (int e) 
    { 
    cout << "An exception occurred. Exception Nr. " << e << '\n'; 
    } 
       std::cout<< "\n"<<"\n"; 
     std::cout<<"Directories found: "<< telDIR<< "\n"; 
     std::cout<<"Files found: "<< telFILES<< "\n"; 
     std::cout<<"Largest File: "<<LargestFileName << " ("<< LargestFile << " kB)"<<"\n";  
     std::cout<<"press any key"; 
     getch();  
    } 

編輯:下面是來自調試器調用堆棧

> File Lister 6.0.exe!std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}, const char * _Val=0x000d51c8) Line 791 + 0x20 bytes C++ 
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\numeric\\interval\\", bool bSearchSubdirectories=false) Line 110 + 0x16 bytes C++ 
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\numeric\\conversion\\", bool bSearchSubdirectories=false) Line 113 C++ 
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multi_index\\detail\\", bool bSearchSubdirectories=false) Line 113 C++ 
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multiprecision\\traits\\", bool bSearchSubdirectories=false) Line 113 C++ 
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multiprecision\\detail\\", bool bSearchSubdirectories=false) Line 113 C++ 
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multiprecision\\cpp_int\\", bool bSearchSubdirectories=false) Line 113 C++ 
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multiprecision\\concepts\\", bool bSearchSubdirectories=false) Line 113 C++ 

調試器中的ostream停在

if (_State == ios_base::goodbit 
    && _Ostr.rdbuf()->sputn(_Val, _Count) != _Count) 
    _State |= ios_base::badbit; 
+0

人們不斷增加的C++代碼到你的C++ 11點的問題。請採取提示! –

+0

如果發生崩潰,您應該做的第一件事是在調試器中運行您的程序,並讓調試器捕獲崩潰。這將告訴你哪裏發生了崩潰,你將能夠檢查函數調用堆棧並將其上傳到你的代碼(如果調試器沒有停止在你的代碼中),然後你可以檢查這些值的所有變量。至少你應該編輯你的問題,向我們展示崩潰代碼中的位置*,最好是所涉及變量的值。 –

+0

[您如何在標準C++中迭代遍歷每個文件/目錄?](http://stackoverflow.com/questions/67273/how-do-you-iterate-through-every-file-directory-recursively -in-標準-c)的 –

回答

1

從快照它的外觀,你已經實現了一個無限遞歸,它不會運行到無限,而是直到你耗盡資源。值得注意的是,在SearchDirectory()的底部,您調用SearchDirectory()時的參數與您初始調用時的參數相同。您需要確保遞歸最終停止。

0

好的,我找到了答案。這一切都與不定式遞歸有關。如果有人有興趣,我已經重寫了代碼。它掃描百秒內的650GB硬盤(超過750K的文件),並返回了一些不錯的數據:

#include <windows.h> 
    #include <iostream> 
    #include <fstream> 
    #include <conio.h> 
    #include <ctype.h> 
    #include <string> 
    #include <string.h> 
    #include <stdio.h> 
    #include <direct.h> 
    #include <list> 
    #include <vector> 
    #include <ctime> 
    #include <iomanip> 

using namespace std; 

    vector <string> myList; 

     int siZe; 
     int siZekB; 
     bool bSearchSubdirectories=true; 
     HANDLE handle; 
     LPCTSTR strPattern; 
     std::string temp; 
     std::string temp1; 
     std::string temp2; 
     std::string temp3; 
     WIN32_FIND_DATA search_data; 
     int DIRPlace; 

     int telDIR=0; 
     int telFILES=0; 
     int telFILESHidden=0; 
     double LargestFile=0; 
     double LargestFileHidden=0; 
     double TotalUsed=0; 
     double TotalUsedHidden=0; 
     string LargestFileName; 
     string LargestFileNameHidden; 
     string SDir; 
     string line,SearD, LineFiller,FrontString, BackString; 
     int SearchDirectory(string FileSearch ,string refvecFiles, 
         bool bSearchSubdirectories); 


int main(int argc, char* argv[]) 
    { 
     system("mode CON: COLS=140 LINES=22"); 
     std::cout<< "Enter directory to be explored: "; 
     getline(cin,SDir); 
     std::cout<< "\n"; 

    clock_t begin = clock(); 



     SearchDirectory("\\*.*",SDir, false); 

     while (!myList.empty()){ 

      SearD=myList.back(); 
      myList.pop_back(); 

      SearchDirectory("\\*.*",SearD.c_str(), false); 
     } 


     clock_t end = clock(); 
     double elapsed_secs = double(end - begin)/CLOCKS_PER_SEC; 

     std::cout<< "\n"<<"\n"; 
     system("cls"); 
     std::cout<<"Directory explored in  : "<<elapsed_secs<<" seconds\n"; 
     std::cout<<"Explored (sub)directories : "<< telDIR<< "\n"; 
     std::cout<<"Unexplored directories  : "<<myList.size()<<"\n\n"; 
     std::cout<<setprecision (2)<<fixed<<"Files found    : "<< telFILES<< " using "<<TotalUsed<<" kB storage\n"; 
     std::cout<<setprecision (2)<<fixed<<"Largest File    : "<<LargestFileName << " ("<< LargestFile << " kB)"<<"\n\n"; 

     std::cout<<setprecision (2)<<fixed<<"Hidden Files found   : "<< telFILESHidden<< " using "<<TotalUsedHidden<<" kB storage\n"; 
     std::cout<<setprecision (2)<<fixed<<"Largest Hidden File  : "<<LargestFileNameHidden << " ("<< LargestFileHidden << " kB)"<<"\n"; 

     std::cout<<"press any key"; 
     getch();  
    } 


    int SearchDirectory(string FileSearch ,string refvecFiles, 
         bool bSearchSubdirectories) 
    { 

     WIN32_FIND_DATA search_data; 
     temp = refvecFiles+ "\\\\"; 
     refvecFiles += "\\\\*.*";   


     HANDLE handle = FindFirstFile(refvecFiles.c_str(), &search_data); 

     if (INVALID_HANDLE_VALUE == handle) 
     { 
      return 0; 
     } 

     do{ 
        if((search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))  //Directory 
         { string filePath =search_data.cFileName; 
          if (strcmp(".", filePath.c_str()) && strcmp("..", filePath.c_str()))    
           { 
            if (filePath == "$RECYCLE.BIN" || filePath == "$Recycle.Bin") 
            continue; 
            temp1=search_data.cFileName; 
            temp2=search_data.dwFileAttributes; 
            myList.push_back(temp+temp1); 
            telDIR++; 
          } 
         }else{ 
           siZe=(search_data.nFileSizeHigh * (MAXDWORD+1)) + search_data.nFileSizeLow; 
           siZekB=((search_data.nFileSizeHigh * (MAXDWORD+1)) + search_data.nFileSizeLow)/1024; 
           temp1=search_data.cFileName; 
           temp2=search_data.dwFileAttributes; 
           if ((search_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0) 
           { TotalUsed=TotalUsed+siZekB; 
            if (siZekB>LargestFile){ 
             LargestFile=siZekB; 
             LargestFileName=temp.substr(0, temp.size()) + "\\" + temp1; 
            } 
            telFILES++; 
           }else{ 
            TotalUsedHidden=TotalUsedHidden+siZekB; 
            if (siZekB>LargestFileHidden){ 
             LargestFileHidden=siZekB; 
             LargestFileNameHidden=temp.substr(0, temp.size()) + "\\" + temp1; 
            } 
            telFILESHidden++; 
           } 
         } 

     }while  (FindNextFile(handle, &search_data) != 0); 
     FindClose(handle); 
     return 0; 
    }