我需要计算MacOS中文件夹的大小。此大小值必须与Finder一致。我已经尝试了几种方法来做到这一点。但结果总是与Finder不同。
以下方法是我尝试过的。
typedef struct{
//getResourceValue in NSURL
unsigned long long fileSize;
unsigned long long fileAllocSize;
unsigned long long totalFileSize;
unsigned long long totalFileAllocSize;
//lstat in posix
unsigned long long statSize;
unsigned long long blockSize;
//NSFileManager
unsigned long long cocoaSizeNo;
unsigned long long cocoaSizeYes
}sizePack;
- (sizePack)foldSize:(NSString *)direString{
sizePack sizeP;
memset(&sizeP, 0, sizeof(sizeP));
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *tempArray = [fileManager contentsOfDirectoryAtPath:direString error:nil];
for (NSString *fileName in tempArray) {
BOOL flag = YES;
NSString *fullPath = [direString stringByAppendingPathComponent:fileName];
if ([fileManager fileExistsAtPath:fullPath isDirectory:&flag]) {
if (!flag) {
NSNumber* FileSize;
NSNumber* FileAllocatedSize;
NSNumber* TotalFileSize;
NSNumber* TotalAllocatedSize;
NSURL* url = [NSURL fileURLWithPath:fullPath];
[url getResourceValue:&FileSize forKey:NSURLFileSizeKey error:nil];
[url getResourceValue:&FileAllocatedSize forKey:NSURLFileAllocatedSizeKey error:nil];
[url getResourceValue:&TotalFileSize forKey:NSURLTotalFileSizeKey error:nil];
[url getResourceValue:&TotalAllocatedSize forKey:NSURLTotalFileAllocatedSizeKey error:nil];
struct stat statbuf;
stat([fullPath UTF8String], &statbuf);
unsigned long long fileSize = [FileSize unsignedLongLongValue];
unsigned long long fileAllocSize = [FileAllocatedSize unsignedLongLongValue];
unsigned long long totalFileSize = [TotalFileSize unsignedLongLongValue];
unsigned long long totalFileAllocSize = [TotalAllocatedSize unsignedLongLongValue];
unsigned long long cocoaSizeNO = [[[NSFileManager defaultManager] fileAttributesAtPath:fullPath traverseLink:NO] fileSize];
unsigned long long cocoaSizeYES = [[[NSFileManager defaultManager] fileAttributesAtPath:fullPath traverseLink:YES] fileSize];
sizeP.fileSize += fileSize;
sizeP.fileAllocSize += fileAllocSize;
sizeP.totalFileSize += totalFileSize;
sizeP.totalFileAllocSize += totalFileAllocSize;
sizeP.statSize += statbuf.st_size;
sizeP.blockSize += statbuf.st_blksize;
sizeP.cocoaSizeNo += cocoaSizeNO;
sizeP.cocoaSizeYes += cocoaSizeYES;
}
else {
sizePack tmp = [self foldSize:fullPath];
sizeP.fileSize += tmp.fileSize;
sizeP.fileAllocSize += tmp.fileAllocSize;
sizeP.totalFileSize += tmp.totalFileSize;
sizeP.totalFileAllocSize += tmp.totalFileAllocSize;
sizeP.statSize += tmp.statSize;
sizeP.blockSize += tmp.blockSize*4096;
sizeP.cocoaSizeNo += tmp.cocoaSizeNo;
sizeP.cocoaSizeYes += tmp.cocoaSizeYes;
}
}
}
return sizeP;
}
答案 0 :(得分:6)
- (unsigned long long) folderSizeWithFSRef:(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];
OSErr fsErr = FSGetCatalogInfoBulk(thisDirEnum,
kMaxEntriesPerFetch, &actualFetched,
NULL, kFSCatInfoDataSizes | kFSCatInfoRsrcSizes |
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
folderSizeWithFSRef:&fetchedRefs[thisIndex]];
}
else
{
// add the size for this item
totalSize += fetchedInfos[thisIndex].dataLogicalSize;
totalSize += fetchedInfos[thisIndex].rsrcLogicalSize;
}
}
if (fsErr == errFSNoMoreItems)
{
break;
}
else
{
// get more items
fsErr = FSGetCatalogInfoBulk(thisDirEnum,
kMaxEntriesPerFetch, &actualFetched,
NULL, kFSCatInfoDataSizes | kFSCatInfoRsrcSizes |
kFSCatInfoNodeFlags, fetchedInfos,
fetchedRefs, NULL, NULL);
}
}
FSCloseIterator(thisDirEnum);
}
return totalSize;
}
- (unsigned long long) sizeOfFileWithURL:(NSURL *)aURL
{
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:aURL.path error:nil];
if ([attr objectForKey:NSFileType] == NSFileTypeDirectory) {
FSRef theFileRef;
CFURLGetFSRef((__bridge CFURLRef)aURL, &theFileRef);
return [self folderSizeWithFSRef:&theFileRef];
} else {
return [[attr objectForKey:NSFileSize] longValue];
}
}
我还注意到finder不会除以1024,而是计算大小时除以1000。奇怪