使用NSDirectoryEnumerator迭代目录,同时从目录中删除文件

时间:2012-11-01 13:33:06

标签: iphone objective-c

如果我这样做:

NSDirectoryEnumerator *directoryEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:cacheDirectory
                                                                  includingPropertiesForKeys:@[NSURLContentAccessDateKey]
                                                                                     options:NSDirectoryEnumerationSkipsHiddenFiles
                                                                                errorHandler:nil];

NSURL *fileURL;
while (fileURL = [directoryEnumerator nextObject])
{
    NSDate *fileDate;
    [fileURL getResourceValue:&fileDate forKey:NSURLContentAccessDateKey error:nil];

    if ([cacheDate compare:fileDate] == NSOrderedDescending) // Delete all files with access date older then cacheDate(defined elsewhere)
        [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
}

目录枚举器是否会“损坏”,例如我是否可以获得意外结果,因为每个文件的索引都会发生变化?

我想使用enumeratorAtURL方法而不是contentsOfDirectoryAtURL因为我必须处理大量文件(超过100,000)。所以contentsOfDirectoryAtURL会占用大量内存。

2 个答案:

答案 0 :(得分:3)

在迭代容器时从容器中删除项目通常是个坏主意。

您可以在数组中保存要删除的所有fileURL,然后遍历数组以删除文件。

这样的事情:

NSMutableArray *urlsToDelete = [[NSMutableArray alloc] init];

NSDirectoryEnumerator *directoryEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:cacheDirectory
                                                                  includingPropertiesForKeys:@[NSURLContentAccessDateKey]
                                                                                     options:NSDirectoryEnumerationSkipsHiddenFiles
                                                                                errorHandler:nil];

NSURL *fileURL;
while (fileURL = [directoryEnumerator nextObject])
{
    NSDate *fileDate;
    [fileURL getResourceValue:&fileDate forKey:NSURLContentAccessDateKey error:nil];

    if ([cacheDate compare:fileDate] == NSOrderedDescending) // Delete all files with access date older then cacheDate(defined elsewhere)
        [urlsToDelete addObject:fileURL];
}

for (NSURL *fileURL in urlsToDelete) {
     [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
}

答案 1 :(得分:2)

根据this Apple documentation on Enumeration

  

在枚举可变集合的元素时,删除,替换或添加它是不安全的。如果您需要在枚举期间修改集合,您可以制作集合的副本并使用副本枚举或在枚举期间收集所需的信息,然后应用更改。

您可能希望将要删除的文件保存在另一个阵列中,然后再执行删除。