【问题标题】:QFileInfo size() is returning shortcut TARGET sizeQFileInfo size() 正在返回快捷方式目标大小
【发布时间】:2018-11-21 12:19:20
【问题描述】:

我正在扫描这样的文件夹大小:

qint64 dirSize = 0;
int fileCount = 0;

for(QDirIterator itDir(someDir, QDir::NoDotAndDotDot|QDir::Files|QDir::Hidden|QDir::System,
                       QDirIterator::Subdirectories);
    itDir.hasNext(); )
{
    itDir.next();
    dirSize += itDir.fileInfo().size();
    ++fileCount;
}

这似乎工作正常。

但是,我注意到包含 Windows 快捷方式 (.lnk) 的文件夹返回的大小比预期的要大得多。原因是返回的是快捷方式目标的大小,而不是快捷方式文件本身的大小。

但是根据QFileInfo documentation

在 Windows 上,符号链接(快捷方式)是 .lnk 文件。报告的 size() 是符号链接的大小(不是链接的目标)[...]

所以我的问题是:我在这里做错了什么?如何获取快捷方式文件的大小?

【问题讨论】:

  • 这真的是 .lnk 文件吗?也许您正在使用不同类型的快捷方式。
  • 是的,这些绝对是 Windows 快捷方式 (.lnk) 文件。
  • itDir应该引用链接的情况下,itDir.filePath()(或itDir.fileInfo().filePath())返回的内容——是否是链接的路径本身还是目标的路径?
  • 两者都按预期返回链接本身的路径。

标签: c++ qt desktop-shortcut qfileinfo


【解决方案1】:

出于测试目的,我创建了一个 Qt 的 DLL 文件的快捷方式。我将此快捷方式放入一个空文件夹中。我还创建了 Qt 的 sdktool.exe 的快捷方式,并将其放在同一个文件夹中。

我还注意到 size() 返回的是实际文件的大小,而不是快捷方式的大小。我记得我在旧项目中的行为有些相似,我所做的是在读取大小之前打开文件。

for (QDirIterator itr(someDir, QDir::NoDotAndDotDot|QDir::Files|QDir::Hidden|QDir::System,
                      QDirIterator::Subdirectories); itr.hasNext();) {
    itr.next();

    // Shows wrong size
    qDebug() << itr.fileName() << ", size (unopened): " << itr.fileInfo().size();

    QFile file(itr.filePath());
    if (file.exists() && file.open(QIODevice::ReadOnly)) {
        // Now the size shows correctly
        qDebug() << "Size when opened: " << file.size();
        file.close();
    }
}

输出:

"sdktool.lnk" , size (unopened):  2817024
Size when opened:  1325
"test.lnk" , size (unopened):  4429312
Size when opened:  951

Windows 10 的文件属性窗口显示“test.lnk”的大小为 951 字节,“sdktool.lnk”的大小为 1325 字节。

【讨论】:

  • 酷,这似乎有效。我已经实现了这个,但首先我检查是否itr.fileInfo().isSymLink(),然后如果file.size() == 0 我添加itr.fileInfo().size()
  • 好收获!我忘了QFileInfo::isSymLink() 存在:)
  • 我发现这种方法不适用于目标无效/不存在的快捷方式。在这两种情况下都会返回 0。
【解决方案2】:

@Rob 的答案在大多数情况下都有效,但当快捷方式的目标不存在/无效时返回 0。
借鉴这种方法,您还可以复制快捷方式并更改扩展名。

因此将它们全部组合成一个函数(我在这里假设打开目标比复制快捷方式更便宜/更安全):

qint64 getFileSize(const QString &path)
{
    qint64 size = 0;
    QFileInfo fileInfo(path);

    if(fileInfo.isSymLink() && fileInfo.size() == QFileInfo(fileInfo.symLinkTarget()).size())
    {
        // Try this approach first
        QFile file(path);
        if(file.exists() && file.open(QIODevice::ReadOnly))
            size = file.size();
        file.close();

        // If that didn't work, try this
        if(size == 0)
        {
            QString tmpPath = path+".tmp";
            for(int i=2; QFileInfo().exists(tmpPath); ++i) // Make sure filename is unique
                tmpPath = path+".tmp"+QString::number(i);

            if(QFile::copy(path, tmpPath))
            {
                size = QFileInfo(tmpPath).size();
                QFile::remove(tmpPath);
            }
        }
    }
    else size = fileInfo.size();

    return size;
}

【讨论】:

    猜你喜欢
    • 2017-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-28
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多