2012-10-09 85 views
2

我需要計算MacOS中文件夾的大小。這個尺寸值必須與Finder一致。我嘗試了幾種方法來做到這一點。但結果總是不同於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

你試過NSFileManager的 - (NSDictionary *)attributesOfItemAtPath:(NSString *)路徑錯誤:(NSError **)錯誤? – J2theC

+0

不要文件夾也有「大小」?如果是這樣,您可以忽略所有文件並累積頂級文件夾和所有包含的文件夾的大小? – trojanfoe

+0

您是否嘗試將您的代碼與Finder的空目錄結果進行比較,以查找具有單個已知文件的目錄? –

回答

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]; 
    } 
} 

我也注意到,取景不除以1024,但1000計算大小時。奇怪的

+2

您應該添加rsrcLogicalSize以及dataLogicalSize。 – JWWalker

+0

謝謝,糾正它 – NSAddict

+0

我重新檢查,文件字節是完全一樣的Finder。 – NSAddict