记得曾经在Windows上做开发时,计算目录的大小需要递归地计算子目录和子文件。现在转到MacOS,操作系统依然没提供相关api (用Finder查看根目录的属性,你会发现在目录大小一列会等很久,这跟Windows上表现一样)。但是,每个人写的这个递归程序都不一定完全相同。今天在网上找到一个据称是速度非常快,结果和系统的完全相同的Carbon实现,特此转载过来。原文见http://www.cocoabuilder.com/archive/cocoa/136498-obtain-directory-size.html#136503
- (unsigned long long) fastFolderSizeAtFSRef:(FSRef*)theFileRef
{
FSIterator thisDirEnum = NULL;
unsigned long long totalSize = 0;
// Iterate the directory contents, recursing as necessary
if (FSOpenIterator(theFileRef, kFSIterateFlat, &thisDirEnum) == noErr)
{
const ItemCount kMaxEntriesPerFetch = 256;
ItemCount actualFetched;
FSRef fetchedRefs[kMaxEntriesPerFetch];
FSCatalogInfo fetchedInfos[kMaxEntriesPerFetch];
// DCJ Note right now this is only fetching data fork sizes... if we decide to include
// resource forks we will have to add kFSCatInfoRsrcSizes
OSErr fsErr = FSGetCatalogInfoBulk(thisDirEnum,
kMaxEntriesPerFetch, &actualFetched,
NULL, kFSCatInfoDataSizes |
kFSCatInfoNodeFlags, fetchedInfos,
fetchedRefs, NULL, NULL);
while ((fsErr == noErr) || (fsErr == errFSNoMoreItems))
{
ItemCount thisIndex;
for (thisIndex = 0; thisIndex < actualFetched; thisIndex++)
{
// Recurse if it's a folder
if (fetchedInfos[thisIndex].nodeFlags &
kFSNodeIsDirectoryMask)
{
totalSize += [self fastFolderSizeAtFSRef:&fetchedRefs[thisIndex]];
}
else
{
// add the size for this item
totalSize += fetchedInfos
[thisIndex].dataLogicalSize;
}
}
if (fsErr == errFSNoMoreItems)
{
break;
}
else
{
// get more items
fsErr = FSGetCatalogInfoBulk(thisDirEnum,
kMaxEntriesPerFetch, &actualFetched,
NULL, kFSCatInfoDataSizes |
kFSCatInfoNodeFlags, fetchedInfos,
fetchedRefs, NULL, NULL);
}
}
FSCloseIterator(thisDirEnum);
}
return totalSize;
}