2012-04-04 17 views
15

¿Hay alguna manera de obtener el tamaño del directorio/tamaño de la carpeta sin atravesar realmente este directorio y agregar el tamaño de cada archivo en él? Idealmente, me gustaría usar alguna librería como boost pero win api estaría bien también.Tamaño de un directorio

+7

Probablemente no. Es por eso que 'right-click -> Properties' tarda tanto en ejecutarse ... – Mysticial

+5

Yo tampoco veo por qué esto debería ser downvoted. Esta es una pregunta muy válida. Vamos chicos. ¿Demasiado localizado? De Verdad. –

+0

No estoy de acuerdo con los votos abajo tampoco ... Esta es una pregunta totalmente válida. – Mysticial

Respuesta

10

Por lo que sé, tiene que hacer esto con la iteración en la mayoría de los sistemas operativos.

Puede echar un vistazo a boost.filesystem, esta biblioteca tiene un directorio_recostive_iterator, iterará a través de cualquier archivo en el sistema obteniendo acumulación del tamaño.

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: se puede hacer este mucho más limpio mediante el uso de std :: acumular y una lambda acabo CBA

3

no me parece que es algo así como que, al menos sin función api win32.

forma nativa para 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

Estoy bastante seguro de que necesitamos multiplicar por (MAXDWORD + 1). Asumiendo unsigned: '(uint64_t) (data.nFileSizeHigh * ((uint64_t) MAXDWORD + 1))' –

2

Debe atravesar los archivos. Obtener un resultado correcto es complicado si hay enlaces duros o puntos de reanálisis en el árbol. Ver el blog post de Raymond Chen para más detalles.

1

Zilog ha escrito una respuesta bastante buena, pero lo haría de forma similar pero diferente.

tengo mi archivo de definición de tipos con:

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

y el código es:

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("..")); 
} 

Este utiliza Unicode y vuelve fallidos directorios si desea eso.

Para llamar uso:

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

Pero no caducan size

+0

Casi funciona, pero falta la función '' IsBrowsePath'' – ibell

Cuestiones relacionadas