2012-04-04 15 views
15

C'è un modo per ottenere le dimensioni della cartella/dimensione della cartella senza effettivamente attraversare questa directory e aggiungere la dimensione di ogni file al suo interno? Idealmente vorrebbe usare qualche libreria come boost, ma vincere api sarebbe ok anche.Dimensione di una directory

+7

Probabilmente no. Ecco perché 'right-click -> Properties' richiede così tanto tempo per essere eseguito ... – Mysticial

+5

Anche io non vedo perché questo dovrebbe essere downvoted. Questa è una domanda molto valida. Forza ragazzi. Troppo localizzato? Veramente. –

+0

Non sono nemmeno d'accordo con i downvotes ... Questa è una domanda totalmente valida. – Mysticial

risposta

10

Per quanto ne so, è necessario farlo con l'iterazione sulla maggior parte dei sistemi operativi.

Si potrebbe dare un'occhiata a boost.filesystem, questa libreria ha un recursive_directory_iterator, itererà comunque sul file sempre accumulando le dimensioni.

http://www.boost.org/doc/libs/1_49_0/libs/filesystem/v3/doc/reference.html#Class-recursive_directory_iterator

include <boost/filesystem.hpp> 
int main() 
{ 
    namespace bf=boost::filesystem; 
    size_t size=0; 
    for(bf::recursive_directory_iterator it("path"); 
     it!=bf::recursive_directory_iterator(); 
     ++it) 
    { 
     if(!bf::is_directory(*it)) 
      size+=bf::file_size(*it); 
    } 
} 

PS: si può fare questo molto più pulita utilizzando std :: si accumulano e un lambda ho appena CBA

3

Non credo che ci sia qualcosa di simile, almeno no funzione win32 api.

nativo per Windows:

void DirectoryInfo::CalculateSize(std::string _path) 
{ 
    WIN32_FIND_DATAA data; 
    HANDLE sh = NULL; 

    sh = FindFirstFileA((_path+"\\*").c_str(), &data); 

    if (sh == INVALID_HANDLE_VALUE) 
    { 
      return; 
    } 

    do 
    { 
     // skip current and parent 
     if (std::string(data.cFileName).compare(".") != 0 && std::string(data.cFileName).compare("..") != 0) 
     { 

      // if found object is ... 
      if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) 
      { 
       // directory, then search it recursievly 
       this->CalculateSize(_path+"\\"+data.cFileName); 


      } else 
      { 
       // otherwise get object size and add it to directory size 
       this->dirSize += (__int64) (data.nFileSizeHigh * (MAXDWORD) + data.nFileSizeLow); 
      } 
     } 

    } while (FindNextFileA(sh, &data)); // do 

    FindClose(sh); 

} 
+0

Sono abbastanza sicuro che dobbiamo moltiplicare per (MAXDWORD + 1). Supponendo unsigned: '(uint64_t) (data.nFileSizeHigh * ((uint64_t) MAXDWORD + 1))' –

2

Devi attraversare i file. Ottenere un risultato corretto è complicato se ci sono collegamenti rigidi o punti di analisi nella struttura. Vedi i dettagli su Raymond Chen blog post.

1

Zilog ha scritto una risposta abbastanza buona, ma lo farei in modo simile ma diverso.

ho il mio file di definizione tipi con:

typedef std::wstring String; 
typedef std::vector<String> StringVector; 
typedef unsigned long long uint64_t; 

e il codice è:

uint64_t CalculateDirSize(const String &path, StringVector *errVect = NULL, uint64_t size = 0) 
{ 
    WIN32_FIND_DATA data; 
    HANDLE sh = NULL; 
    sh = FindFirstFile((path + L"\\*").c_str(), &data); 

    if (sh == INVALID_HANDLE_VALUE) 
    { 
     //if we want, store all happened error 
     if (errVect != NULL) 
      errVect ->push_back(path); 
     return size; 
    } 

    do 
    { 
     // skip current and parent 
     if (!IsBrowsePath(data.cFileName)) 
     { 
      // if found object is ... 
      if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) 
       // directory, then search it recursievly 
       size = CalculateDirSize(path + L"\\" + data.cFileName, NULL, size); 
      else 
       // otherwise get object size and add it to directory size 
       size += (uint64_t) (data.nFileSizeHigh * (MAXDWORD) + data.nFileSizeLow); 
     } 

    } while (FindNextFile(sh, &data)); // do 

    FindClose(sh); 

    return size; 
} 

bool IsBrowsePath(const String& path) 
{ 
    return (path == _T(".") || path == _T("..")); 
} 

Questo utilizza Unicode e ritorna fallito dirs se si desidera che.

Per chiamare l'uso:

StringVector vect; 
CalculateDirSize(L"C:\\boost_1_52_0", &vect); 
CalculateDirSize(L"C:\\boost_1_52_0"); 

Ma mai passare size

+0

Quasi funziona, ma manca la funzione '' IsBrowsePath'' – ibell

Problemi correlati