QFileInfo size () возвращает размер ярлыка TARGET

Я сканирую размер папки следующим образом:

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:

В Windows символические ссылки (ярлыки) представляют собой файлы .lnk. Указанный размер () соответствует символической ссылке (а не цели ссылки) […]

Поэтому мой вопрос: что я здесь делаю не так? Как получить размер файла ярлыка?

1

Решение

Для целей тестирования я создал ярлык одного из DLL-файлов Qt. Я поместил этот ярлык в пустую папку. Я также создал ярлык sdktool.exe в Qt и поместил его в ту же папку.

Я также заметил, что 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 байт.

1

Другие решения

Ответ @ Роба работает в большинстве случаев, но возвращает 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;
}
0

По вопросам рекламы [email protected]