如何计算文件夹的大小。 (此大小必须与Finder一致。)

时间:2012-10-09 14:09:27

标签: objective-c macos cocoa core-foundation

我需要计算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;
}

1 个答案:

答案 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。奇怪