为了账号安全,请及时绑定邮箱和手机立即绑定

如何计算文件夹的大小?

如何计算文件夹的大小?

iOS
DIEA 2019-10-08 09:53:32
我正在创建一个文件夹,以使用iPhone App在“文档”中缓存图像。我希望能够将此文件夹的大小减小到1MB,因此我需要检查文件夹的大小(以字节为单位)。我有代码来计算文件的大小,但是我需要文件夹的大小。最好的方法是什么?
查看完整描述

3 回答

?
开心每一天1111

TA贡献1836条经验 获得超13个赞

tl; dr

所有其他答案都关闭了:)


问题

我想在这个老问题上加上两分钱,因为似乎有很多答案都非常相似,但在某些情况下得出的结果却非常不准确。


要了解为什么我们首先必须定义文件夹的大小。以我的理解(可能是OP之一),它是目录(包括其所有内容)在卷上使用的字节数。或者,换一种说法:


如果目录将被完全删除,则该空间变为可用。


我知道,此定义不是解释问题的唯一有效方法,但我确实认为这是大多数用例的根源。


错误

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


卷上使用的空间以块为单位递增,而不是以字节为单位递增。即使是一个字节的文件也至少使用一个块。

文件包含元数据(如任意数量的扩展属性)。此数据必须放在某处。

HFS部署文件系统压缩,以实际使用较少的字节(而不是其实际长度)存储文件。

所有这些原因使现有的答案产生不精确的结果。因此,我提议对此扩展NSFileManager(由于长度而在github 上的代码:Swift 4,Objective C)来解决这个问题。它的速度也相当快,特别是对于包含大量文件的目录。


该解决方案的核心是使用NSURL的NSURLTotalFileAllocatedSizeKey或NSURLFileAllocatedSizeKey性的判定来检索文件的大小。


测试

我还建立了一个简单的iOS测试项目,展示了解决方案之间的差异。它显示了在某些情况下结果可能完全错误。


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


证明

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


请参阅Rob Napier的评论,以了解仍有改进的空间。


性能

但是还有另一个优点:在计算包含1000个文件的目录的大小时,在我的iPhone 6上,此folderSize:方法大约需要250毫秒,而allocatedSize在35毫秒内遍历相同的层次结构。


这可能是由于使用NSFileManager的new(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)


查看完整回答
反对 回复 2019-10-08
?
阿晨1998

TA贡献2037条经验 获得超6个赞

为亚历克斯加油打气,您已经提供了很多帮助,现在已经编写了以下功能,可以发挥作用...


- (unsigned long long int)folderSize:(NSString *)folderPath {

    NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];

    NSEnumerator *filesEnumerator = [filesArray objectEnumerator];

    NSString *fileName;

    unsigned long long int fileSize = 0;


    while (fileName = [filesEnumerator nextObject]) {

        NSDictionary *fileDictionary = [[NSFileManager defaultManager] fileAttributesAtPath:[folderPath stringByAppendingPathComponent:fileName] traverseLink:YES];

        fileSize += [fileDictionary fileSize];

    }


    return fileSize;

}

它提供了与Finder一样的确切字节数。


顺便说一句,Finder返回两个数字。一个是磁盘上的大小,另一个是实际的字节数。


例如,当我在一个文件夹中运行此代码时,它以130398的“文件大小”返回代码中。当我在Finder中签入时,它说磁盘上的大小为201KB(130,398字节)。


有点不确定此处的实际大小(201KB或130,398字节)。现在,我会安全地将限制减少一半,直到我知道这到底意味着什么...


如果有人可以向这些不同的号码添加更多信息,我将不胜感激。


干杯,


查看完整回答
反对 回复 2019-10-08
  • 3 回答
  • 0 关注
  • 700 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信