使用文件管理器迭代目录占用大量内存
Posted
技术标签:
【中文标题】使用文件管理器迭代目录占用大量内存【英文标题】:iterate dirs using filemanager take up quite a lot memory 【发布时间】:2013-07-09 03:15:35 【问题描述】:我正在使用NSFileManager
的enumeratorAtPath
方法来计算特定目录下的文件大小。
NSString *iterDir = @"/path/to/dir/";
NSFileManager *fm = [[NSFileManager alloc] init];
NSDirectoryEnumerator *dirEnum = [fm enumeratorAtPath:iterDir];
NSString *file;
BOOL isDir;
long long fileSize = 0;
while (file = [dirEnum nextObject])
@autoreleasepool
file = [iterDir stringByAppendingString:file];
if ([fm fileExistsAtPath:file isDirectory:&isDir])
if (!isDir)
NSError *error;
NSDictionary *attributes = [fm attributesOfItemAtPath:file error:&error];
if (!error)
fileSize += [attributes[@"NSFileSize"] doubleValue];
NSLog(@"fileSize:%lld", fileSize);
结果是这样的:
有时是这样的:
内存是干什么用的?为什么连在外面加个@autoreleasepool
都没效果?
【问题讨论】:
使用 Instruments 找出导致它的原因。然后回来报告,因为我很好奇。 【参考方案1】:我无法让您的示例按照提供的方式运行,即使替换为有效的目录路径也是如此。您的代码有一些问题。这是您需要进行的一些更改。一个是这一行:
file = [iterDir stringByAppendingString:file];
真的应该改成:
file = [iterDir stringByAppendingPathComponent:file];
后者要安全得多,因为无论您的目录路径是否以/
结尾,它都会正确附加路径。 (在我的情况下,您的原始文件失败了,因为我使用 [@"~/Desktop" stringByExpandingTildeInPath]
来获取我的目录路径;这会产生一个没有尾随 /
的路径。)
然后在你的循环中,你在堆栈上分配一个未初始化的变量error
,通过引用传递它,然后询问它是否是nil
。这是一个错误的问题,因为除非方法返回 nil(或 NO
,取决于方法),否则无法保证 error
的值。相反,您应该询问 attributes
是否为 nil
,并将 NULL
传递给 error
,因为否则您似乎对此不感兴趣。所以总结一下,改变这个:
NSError *error;
NSDictionary *attributes = [fm attributesOfItemAtPath:file error:&error];
if (!error)
到这里:
NSDictionary *attributes = [fm attributesOfItemAtPath:file error:NULL];
if (attributes != nil)
我保证,解决第二个问题意味着您的结果将更加一致。同时,当我运行代码时,我得到的结果看起来可能是 NSLog()
语句中的有效值。
无所谓,您也可以在循环中使用快速枚举。而不是:
while (file = [dirEnum nextObject])
你可以改用:
for (file in dirEnum)
现在回答您最初的问题。您分配的内存变大的原因是您的包含文件名的字符串被分配到您的 @autoreleasepool
指令范围之外的主自动释放池中,它们将一直坐在那里直到该池清空。但是,在循环中使用自己的自动释放池仍然是一件好事。
【讨论】:
感谢 4 条优化建议,它们真的很有帮助。但仍然无法修复/解释内存问题。不能跑?您可以提供像/Users/yourname/Desktop
这样的绝对路径。它应该做的工作。
绝对路径可以工作,但是当使用其他方法生成没有尾部斜杠的路径时,例如我使用的方法呢?
当然stringByAppendingPathComponent:
有效,但对结果没有影响。以上是关于使用文件管理器迭代目录占用大量内存的主要内容,如果未能解决你的问题,请参考以下文章