ios - 如何计算文件夹的大小?

标签 ios iphone nsfilemanager

我正在使用我的 iPhone 应用程序创建一个文件夹来缓存 Documents 中的图像。我希望能够将此文件夹的大小保持在 1MB,因此我需要检查我的文件夹的大小(以字节为单位)。

我有计算 size of file 的代码, 但我需要文件夹的大小。

执行此操作的最佳方法是什么?

最佳答案

tl;博士

所有其他答案均已关闭 :)

问题

我想对这个老问题补充我的两分钱,因为似乎有很多答案都非常相似,但在某些情况下产生的结果非常不精确。

要理解为什么我们首先必须定义文件夹的大小。根据我的理解(可能是 OP 中的一个),它是包含其所有内容的目录在卷上使用的字节数。或者,换句话说:

如果目录将被完全删除,它是可用的空间。

我知道这个定义不是解释问题的唯一有效方式,但我确实认为这是大多数用例的归结。

错误

现有的答案都采用了一种非常简单的方法:遍历目录内容,将(常规)文件的大小相加。这并没有考虑到一些微妙之处。

  • 卷上使用的空间以 block 而不是字节为单位递增。即使一个字节的文件也至少使用一个 block 。
  • 文件携带元数据(如任意数量的扩展属性)。这些数据必须去某个地方。
  • HFS 部署文件系统压缩,以使用比实际长度更少的字节实际存储文件。

解决方案

所有这些原因导致现有答案产生不精确的结果。所以我在 NSFileManager 上提出这个扩展(由于长度在 github 上的代码:Swift 4Objective C)来解决这个问题。它也快了很多,尤其是对于包含大量文件的目录。

解决方案的核心是使用 NSURLNSURLTotalFileAllocatedSizeKeyNSURLFileAllocatedSizeKey 属性来检索文件大小。

测试

我还设置了 a simple iOS test project ,展示解决方案之间的差异。它显示了在某些情况下结果可能是多么错误。

在测试中,我创建了一个包含 100 个小文件(从 0 到 800 字节不等)的目录。从其他答案复制的 folderSize: 方法计算出总共 21 kB,而我的 allocatedSize 方法产生 401 kB。

证明

我通过计算删除测试目录前后卷上可用字节的差异,确保 allocatedSize 的结果更接近正确值。在我的测试中,差异总是完全等于 allocatedSize 的结果。

请查看 Rob Napier 的评论以了解仍有改进空间。

性能

但还有另一个优势:在计算包含 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)

关于ios - 如何计算文件夹的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2188469/

相关文章:

objective-c - 使用 ARC 发布

ios - 从 AppDelegate 调用的 UIViewController 中的方法不使用现有对象

iphone - 如何在编辑模式下向 UITableViewCell 添加 subview 并调整其大小?

iphone - Plist不会复制到文档目录

ios - NSFileManager.defaultManager().fileExistsAtPath 返回 false 而不是 true

ios - XIB 中的 UITabelViewCell 将被实例化更多次

ios - 如何在 objective-c 中以自定义方式对包含数字和字符的字符串数组进行排序?

javascript - 是否可以使用 Javascript 访问 iPhone 加速度计?

iphone - 我将如何扭转这个等式?

objective-c - NSFilemanager 和安全删除