17

Вопрос по winapi, windows, c, c++ – Размер каталога [дубликат]

This question already has an answer here:

Есть ли способ получить размер каталога / размер папки без фактического обхода этого каталога и добавления размера каждого файла в нем? В идеале хотелось бы использовать некоторую библиотеку, такую как boost, но win api тоже подойдет.

  • Error: User Rate Limit ExceededIsBrowsePathError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded(uint64_t)(data.nFileSizeHigh * ((uint64_t)MAXDWORD + 1))

    от
  • Error: User Rate Limit Exceeded

    от
  • Возможно нет. Вот почемуright-click -> Properties так долго бегать ...

    от Mysticial
  • Research Effort, что является причиной номер один, если вы наведите указатель мыши на кнопку понижения. Простой поиск в Google предоставит множество "Вы должны пройти".

    от Brian Roach
  • ИМХО, сам факт, что Windows Explorer явно выполняет обход, должен быть достаточно намеком.

    от Seva Alekseyev
  • Я также не согласен с отрицательными голосами ... Это совершенно правильный вопрос.

    от Mysticial
  • Я тоже не понимаю, почему это должно быть опущено. Это очень актуальный вопрос. Давайте, ребята. Слишком локализовано? В самом деле.

    от Niklas B.
  • 4

    Я не думаю

    что есть что-то подобное, по крайней мере, нет функции Win32 API.

    Родной для окон:

    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);
    
    } 
    

  • 14

    Насколько я знаю

    вы должны делать это с итерацией в большинстве операционных систем.

    Вы можете взглянуть на boost.filesystem, у этой библиотеки есть recursive_directory_iterator, он будет перебирать любой файл в системе, получая накопительный размер.

    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: вы можете сделать это намного чище, используя std :: аккумулятор и лямбда, я просто CBA

  • 2

    Вы должны пройти через файлы. Получить правильный результат сложно

    если в дереве есть жесткие ссылки или точки повторного анализа. Смотрите Рэймонда ЧенаСообщение блога для деталей.

  • 1

    Зилог написал неплохой ответ

    но я бы сделал это похожим, но другим способом.

    У меня есть файл определения типов с:

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

    и код:

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

    Это использует UNICODE и возвращает неудачные каталоги, если вы этого хотите.

    Для звонка используйте:

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

    Но никогда не пройтиsize