如何在目录遍历中获取文件大小?

时间:2011-08-17 16:57:48

标签: c++ qt

当我使用递归来查看每个文件时,如何获取文件的大小? 我收到了下一个错误:

  

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 个答案:

答案 0 :(得分:8)

首先清理一下代码。

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

如果你想保持ui被动,在一个单独的线程中进行计算,在每个文件中调用processEvent()是一个负担。 您还应该使用quint64(unsigned long long)来处理大文件(&gt; 2Go) 但是,目前还不清楚崩溃的位置。

答案 1 :(得分:1)

改变这个:

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()

答案 2 :(得分:1)

崩溃是因为你一次又一次递归地评估同一个文件夹。 语句sizex += this->dir_size(fileInfo.path());以相同的文件夹名称递归调用相同的函数。 所以你的堆栈会不断增长并最终会内存不足。

fileInfo.path()提供相同的(父)文件夹。

fileInfo.filePath()为文件名提供路径

将其更改为sizex += this->dir_size(fileInfo.filePath());,这应该解决它

答案 3 :(得分:0)

这是获取目录大小的更为开发的答案。其结果与实用程序“du”(磁盘使用情况)的结果相匹配。

这考虑到Linux认为目录条目本身具有大小。它在Linux和Windows中正确处理符号链接/快捷方式(而不是忽略它们!)。这也允许ui以更合乎逻辑的方式“呼吸”,而不是假设新的目录遍历是暂时“休息”的时刻。

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