我正在编写一个程序,可以在运行时处理数百个文件。现在,每个文件和文件夹都存储在我创建的对象中(它包含文件路径,文件类型,文件大小,指向文件中偏移量的指针,以及它是否是目录),并且这些对象放在NSMutableArray中。这个问题的一个大问题是在处理所有文件时,我需要获取每个文件夹中所有文件的统计信息。我使用2个嵌套for循环来做这个,性能很糟糕。
我的问题是:有没有更有效的方法来存储cocoa中的文件和文件夹列表(除了NSMutableArray,集合等),这样我就可以快速访问这些文件夹中的所有文件夹和所有对象?是否有一些结构可以创建一个文件夹数组以及位于该父文件夹中的文件和文件夹数组?
答案 0 :(得分:3)
现在,每个文件和文件夹都存储在我创建的对象中(它包含文件路径,文件类型,文件大小,指向文件中偏移量的指针,如果它是目录),并且这些对象放在的NSMutableArray。
这是正确的解决方案。 C数组比较棘手,因为你必须自己处理大小管理,而不是检查边界。
这个问题的一个大问题是在处理所有文件时,我需要获取每个文件夹中所有文件的统计信息。我使用2个嵌套for循环来做这个,性能很糟糕。
您是否使用Shark和/或乐器进行了分析?这是你应该检查的第一件事,如果你还没有。瓶颈可能不在你想象的地方。在您进行分析之前,请停止阅读此答案(以及任何其他答案)。
如果您当前正在使用此任务阻止主线程,请考虑使用NSOperationQueue。对于顶级中的每个项目,如果它是文件,则添加检查文件的操作,如果它是目录,则添加将对目录内容执行相同迭代的操作。如果你可以要求Snow Leopard,你可以在这里找到方便的块,因为你不必明确告诉目录库存操作将哪个队列添加检查文件操作。
您可能应该限制一次运行队列的操作数,以免最终运行太多。 Mike Ash has details(该帖子与GCD有关,但截至Snow Leopard,NSOperationQueue基于GCD)。
假设您在UI中显示正在运行的总计,您可以使用主队列来保存(可能是基于块的)操作,这些操作会向总计中添加新信息。如果您支持Leopard,您可以创建自己的“主”队列,但是您必须自己在主线程上运行操作。
顺便说一句,如果你总计文件大小,你应该考虑是否要在inode上进行统一。如果我将200 MiB文件硬链接到其他三个地方,你会看到四个文件,但它们都是同一个文件,所以它们只占用200 MiB而不是800.
答案 1 :(得分:2)
您可能还想考虑树状结构。您有一个与文件路径“/”对应的根节点。然后root有很多孩子,分别是“/ System”,“/ etc”,“/ Library”,“/ Users”等。
在此树中添加节点时,可以让它渗透并将新节点的文件大小添加到父节点(以便树在根节点中始终具有正确的卷大小)。或者您可以根据需要计算大小(递归,最有可能)并返回。
至于首先检索路径,您可能找到了NSFileManager
。您还应该查看NSDirectoryEnumerator
和较低级FSGetCatalogInfoBulk
。
答案 2 :(得分:1)
您可以使用C数组而不是Cocoa集合。这可能会更快 一些与性能比较的链接:
答案 3 :(得分:1)
将NSMutableDictionary
与文件目录一起用作密钥,将NSMutableArray
个文件用作对象。您将能够快速迭代目录。
您还可以使用[NSString pathComponents]
拆分目录,并使用词典词典来保存路径的每个部分(树)。您甚至可以在树中混合文件和词典,并使用[foo isKindOfClass:[NSDictionary class]]
将它们区分开来。
这是我正在讨论的JSON版本(可以很好地转换为Cocoa类):
/foo/bar/bazfile
& /foo/quzfile
=
{"foo": {
"bar": {
"bazfile": fileinfo
},
"quzfile": fileinfo
}