2015-12-23 4 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();  
    } 

EDIT: Ниже приведен снимок из отладчика Call Stack

> 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-recursive -в-стандарт-с) –

ответ

1

От взгляды этого, вы внедрили бесконечную рекурсию, которая просто не будет работать до бесконечности, а только до тех пор, пока вы не исчерпаете ресурсы. Примечательно, что в нижней части SearchDirectory() вы вызываете SearchDirectory() с теми же параметрами, что и в случае, когда вы его назовете. Вы должны убедиться, что рекурсия прекратится.

0

ОК, я нашел ответ. Все это связано с инфинитивной рекурсией. Если кому-то интересно, я переписал код. Он отсканировать жесткий диск 650GB (более 750k файлов) в течение 100 секунд и возвращает некоторые интересные данные:

#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; 
    } 
Смежные вопросы