Как я могу получить размер файла при обходе каталога? - PullRequest
6 голосов
/ 17 августа 2011

Как я могу получить размер файла, когда я использую рекурсию для просмотра каждого файла?Я получаю следующую ошибку:

project.exe завершен с кодом -1073741819

int dir_size(const QString _wantedDirPath)
{
    long int sizex = 0;
    QFileInfo str_info(_wantedDirPath);
    if (str_info.isDir())
    {
        QDir dir(_wantedDirPath);
        QStringList ext_list;
        dir.setFilter(QDir::Files | QDir::Dirs |  QDir::Hidden | QDir::NoSymLinks);
        QFileInfoList list = dir.entryInfoList();

        for(int i = 0; i < list.size(); ++i)
        {
            QFileInfo fileInfo = list.at(i);
            if ((fileInfo.fileName() != ".") && (fileInfo.fileName() != ".."))
            {
                sizex += (fileInfo.isDir()) ? this->dir_size(fileInfo.path()) : fileInfo.size():
                QApplication::processEvents();
            }
        } 
    } 

    return sizex;
}

Ответы [ 4 ]

8 голосов
/ 17 августа 2011

Начните с очистки кода немного.

quint64 dir_size(const QString & str)
{
    quint64 sizex = 0;
    QFileInfo str_info(str);
    if (str_info.isDir())
    {
        QDir dir(str);
        QFileInfoList list = dir.entryInfoList(QDir::Files | QDir::Dirs |  QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot);
        for (int i = 0; i < list.size(); ++i)
        {
            QFileInfo fileInfo = list.at(i);
            if(fileInfo.isDir())
            {
                    sizex += dir_size(fileInfo.absoluteFilePath());
            }
            else 
                sizex += fileInfo.size();

        }
    }
    return sizex;
} 

Если вы хотите, чтобы пользовательский интерфейс реагировал, делайте вычисления в отдельном потоке, вызовите processEvent () для каждого файла - это бремя. Вы также должны использовать quint64 (unsigned long long) для обработки больших файлов (> 2Go) Но не ясно, где происходит авария.

1 голос
/ 17 августа 2011

Это сбой, потому что вы рекурсивно оцениваете одну и ту же папку снова и снова.Оператор sizex += this->dir_size(fileInfo.path()); рекурсивно вызывает одну и ту же функцию с тем же именем папки.Таким образом, ваш стек продолжает расти и в конечном итоге не хватает памяти.

fileInfo.path() дает ту же (родительскую) папку.

fileInfo.filePath() дает имя файла с путем

Изменитьsizex += this->dir_size(fileInfo.filePath()); и это должно исправить

1 голос
/ 17 августа 2011

Изменить это:

if(fileInfo.isDir())
{
     sizex += this->get_dir_size(fileInfo.path());
     QApplication::processEvents();
}

до

if(fileInfo.isDir())
{
     sizex += dir_size(fileInfo.path()); //call recursively!
     QApplication::processEvents();
}

Почему вы звоните get_dir_size() - что бы это ни было? Вам следует позвонить dir_size(), если вы хотите вычислить размер рекурсивно.

0 голосов
/ 06 ноября 2017

Вот более подробный ответ для получения размера каталога. Его результаты совпадают с результатами утилиты "du" (Disk Usage).

При этом учитывается, что Linux считает, что сама запись каталога имеет размер. Он правильно обрабатывает символьные ссылки / ярлыки как в Linux, так и в Windows (а не игнорирует их!). Это также позволяет пользовательскому интерфейсу «дышать» более логичным образом, чем предполагать, что новый обход каталога - это точка, в которой можно «отдохнуть» на мгновение.

#ifdef Q_OS_WIN32
#include <sys/stat.h>
long getStdFileSize( const std::string &filename )
{
    struct stat stat_buf;
    int rc = stat( filename.c_str(), &stat_buf );
    return rc == 0 ? stat_buf.st_size : -1;
}
#endif

// designed to match the results of the standard
// cross platform utility "du" (Disk Usage)
// compare to du -b [path]
quint64 diskUsage( const QString &absPath, int &itemCount )
{
    static const int UI_REFRESH_FREQ_ITEMS_TRAVERSED( 100 );
    QFileInfo parentInfo( absPath );
    if( parentInfo.exists() ) itemCount++;    
    quint64 totalBytes =
        parentInfo.isSymLink() ?
// handle symlink size correctly
#ifdef Q_OS_WIN32
        getStdFileSize( absPath.toStdString() )
#else
        parentInfo.symLinkTarget().length()
#endif
        : parentInfo.size();
    if( parentInfo.isDir() )
    {
        QFileInfoList childInfoList = QDir( absPath ).entryInfoList(
            QDir::Files | QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot );
        foreach( const QFileInfo &childInfo, childInfoList )
        {
            totalBytes += diskUsage(
                childInfo.absoluteFilePath(), itemCount );
            // prevent ui lockup, as this can potentially take a long time
            if( (itemCount % UI_REFRESH_FREQ_ITEMS_TRAVERSED)==0 )
                QGuiApplication::processEvents();
        }
    }
    return totalBytes;
}

// convenience overload
quint64 diskUsage( const QString &absPath )
{
    int itemCount=0;
    return diskUsage( absPath, itemCount );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...