ТЛ; др
Все остальные ответы отключены:)
Проблема
Я бы хотел добавить свои два цента к этому старому вопросу, так как, кажется, есть много ответов, которые очень похожи, но дают результаты, которые в некоторых случаях очень неточны.
Чтобы понять, почему мы сначала должны определить, каков размер папки . В моем понимании (и, вероятно, в одном из OP) это количество байтов, которое каталог, включая все его содержимое, использует на томе. Или, по-другому:
Это пространство становится доступным, если каталог будет полностью удален.
Я знаю, что это определение не единственный верный способ интерпретации вопроса, но я думаю, что это то, к чему сводится большинство вариантов использования.
Error
Все существующие ответы используют очень простой подход: просмотрите содержимое каталога, сложив размеры (обычных) файлов. Это не учитывает пару тонкостей.
- Пространство, используемое для увеличения тома в блоках , а не в байтах. Даже однобайтовый файл использует хотя бы один блок.
- Файлы содержат метаданные (как любое количество расширенных атрибутов). Эти данные должны куда-то идти.
- HFS развертывает файловую систему сжатие , чтобы фактически сохранить файл, используя меньше байтов, чем его реальная длина.
Решение
Все эти причины заставляют существующие ответы давать неточные результаты. Поэтому я предлагаю это расширение на NSFileManager
(код на github из-за длины: Swift 4 , Objective C ) для устранения проблемы. Это также немного быстрее, особенно с каталогами, содержащими много файлов.
Суть решения заключается в использовании NSURL
* NSURLTotalFileAllocatedSizeKey
или NSURLFileAllocatedSizeKey
свойств для получения размеров файлов.
Тест
Я также создал простой тестовый проект iOS , демонстрирующий различия между решениями. Он показывает, насколько ошибочными могут быть результаты в некоторых сценариях.
В тесте я создаю каталог, содержащий 100 маленьких файлов (от 0 до 800 байт). Метод folderSize:
, скопированный из какого-либо другого ответа, вычисляет в общей сложности 21 кБ, в то время как мой метод allocatedSize
дает 401 кБ.
Доказательство
Я удостоверился, что результаты allocatedSize
ближе к правильному значению, вычислив разницу доступных байтов в томе до и после удаления тестового каталога. В моих тестах разница всегда была точно равна результату allocatedSize
.
Пожалуйста, ознакомьтесь с комментарием Роба Напира, чтобы понять, что еще есть возможности для улучшения.
Performance
Но есть и другое преимущество: при расчете размера каталога с 1000 файлами на моем iPhone 6 метод folderSize:
занимает около 250 мс, а allocatedSize
проходит по той же иерархии за 35 мс.
Это, вероятно, связано с использованием NSFileManager
нового (ish) enumeratorAtURL:includingPropertiesForKeys:options:errorHandler:
API для обхода иерархии. Этот метод позволяет вам указать предварительно выбранные свойства для элементов, которые будут повторяться, в результате чего меньше io.
Результаты
Test `folderSize` (100 test files)
size: 21 KB (21.368 bytes)
time: 0.055 s
actual bytes: 401 KB (401.408 bytes)
Test `allocatedSize` (100 test files)
size: 401 KB (401.408 bytes)
time: 0.048 s
actual bytes: 401 KB (401.408 bytes)
Test `folderSize` (1000 test files)
size: 2 MB (2.013.068 bytes)
time: 0.263 s
actual bytes: 4,1 MB (4.087.808 bytes)
Test `allocatedSize` (1000 test files)
size: 4,1 MB (4.087.808 bytes)
time: 0.034 s
actual bytes: 4,1 MB (4.087.808 bytes)