2009-08-14 70 views
6

現在,我使用這個代碼來獲得一個文件夾的大小:獲取文件夾大小的簡單方法(ObjC/Cocoa)?

NSArray *contents; 
     NSEnumerator *enumerator; 
     NSString *path; 
     contents = [[NSFileManager defaultManager] subpathsAtPath:folderPath]; 
     enumerator = [contents objectEnumerator]; 
     while (path = [enumerator nextObject]) { 
      NSDictionary *fattrib = [[NSFileManager defaultManager] fileAttributesAtPath:[folderPath stringByAppendingPathComponent:path] traverseLink:YES]; 
      fileSize +=[fattrib fileSize]; 
     } 

     [contents release]; 
     [path release]; 

的問題是,它的高度innacurate。它要麼增加幾兆字節,要麼從實際大小中減去幾兆字節。例如,我得到一個.app包的文件大小,這個方法報告了16.2MB,而實際的東西是15.8。

獲取文件夾大小的最佳方法是什麼?

謝謝

+0

有人嗎? :-) – 2011-12-01 22:59:42

回答

5

我今天需要這樣做,我發現this post on the Cocoa-dev list中的代碼超級快,並且與Finder對字節所說的內容相匹配。 (不要忘記在kFSCatInfoRsrcSizes標誌中的OR,這樣你也可以獲得資源分叉的大小!)

如果您需要更多關於如何使用它的解釋,請留下評論,我將編輯這篇文章。 =)

+0

謝謝,什麼是轉換包含FSRef路徑的NSString的好方法? 謝謝 – indragie 2009-08-15 00:13:29

+0

剛剛回答你的問題。 =) – 2009-08-15 00:59:02

+0

@Dave,這個鏈接是壞的,你可以更新它或放置代碼來回答? – Igor 2017-02-09 20:33:16

1

這通常是如何完成的。 2種可能性:

  1. 檢查您的字節 - >兆字節的轉換例程。另外,你想要兆字節或兆字節? (這可能取決於你正在比較的內容。)

  2. 嘗試將traverseLink參數傳遞爲NO。捆綁中的符號鏈接可能指向其他的東西,你正在比較它的例程將不會考慮。你要麼將數據包中的某些東西計算兩次,要麼將包含在包之外的東西(最有可能是前者)。

4

fileSize的文檔聲明它不包含資源分支的大小。您可能需要使用Carbon File Manager API來可靠地計算目錄大小。

+0

啊,是的,那是另一種可能性。我忘了那個。 – kperryua 2009-08-14 01:53:14

2

我只是想第二次Dave DeLong關於Cocoa-dev上的帖子的建議,但是請加上一條警告性提示,以確保閱讀該帖子中的所有帖子。 Rosyna有一個特別值得注意的地方。在我的情況下,我遵循這個建議(將每次獲取的最大物品數量改爲40),並看到了一個速度跳躍以及一個令人討厭的崩潰錯誤。

+1

可能更好地添加這個作爲他的回答的評論,以便他們保持相關,即使他們在頁面上的位置發生變化。 – 2009-08-14 16:30:07

+0

我在戴夫德龍的方法有問題。我使用此代碼將我的NSString轉換爲FSRef: FSRef f; OSStatus os_status = FSPathMakeRef((const UInt8 *)[filePath fileSystemRepresentation],&f,NULL); \t \t如果(os_status == NOERR){ \t \t \t的NSLog(@ 「成功」); \t \t} 然後我嘗試運行方法: [自fastFolderSizeAtFSRef:F]; 但是我得到錯誤「fastFolderSize的參數1的不兼容類型」 任何想法?謝謝 – indragie 2009-08-14 16:44:40

2

我知道這是一個老話題。但沒有人在那裏尋找如何做到這一點的答案,

[[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]; 
     if (isDir) { 
      NSPipe *pipe = [NSPipe pipe]; 
      NSTask *t = [[[NSTask alloc] init] autorelease]; 
      [t setLaunchPath:@"/usr/bin/du"]; 
      [t setArguments:[NSArray arrayWithObjects:@"-k", @"-d", @"0", path, nil]]; 
      [t setStandardOutput:pipe]; 
      [t setStandardError:[NSPipe pipe]]; 

      [t launch]; 

      [t waitUntilExit]; 

      NSString *sizeString = [[[NSString alloc] initWithData:[[pipe fileHandleForReading] availableData] encoding:NSASCIIStringEncoding] autorelease]; 
      sizeString = [[sizeString componentsSeparatedByString:@" "] objectAtIndex:0]; 
      bytes = [sizeString longLongValue]*1024; 
     } 
     else { 
      bytes = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil] fileSize]; 
     } 

它將使用終端來確定大小以字節爲單位的文件夾。它將使用NSFileManager中構建的Cocoa來獲取文件的大小。它速度非常快,並且獲取了查找器報告的確切大小。

+0

雖然這肯定會起作用,但您在創建另一個進程(可能非常昂貴)或者使用「NSFileManager」時性能受到影響,在計算大小時不包含資源分支。 – 2010-01-19 15:20:20

1

此代碼作爲NSFileManager類的擴展(類別)。它彙總所有文件夾內容的大小。 請注意,錯誤處理可能會增強。

@interface NSFileManager(Util) 

     - (NSNumber *)sizeForFolderAtPath:(NSString *) source error:(NSError **)error; 

    @end 

    @implementation NSFileManager(Util) 

     - (NSNumber *)sizeForFolderAtPath:(NSString *) source error:(NSError **)error 
     { 
      NSArray * contents; 
      unsigned long long size = 0; 
      NSEnumerator * enumerator; 
      NSString * path; 
      BOOL isDirectory; 

      // Determine Paths to Add 
      if ([self fileExistsAtPath:source isDirectory:&isDirectory] && isDirectory) 
      { 
       contents = [self subpathsAtPath:source]; 
      } 
      else 
      { 
       contents = [NSArray array]; 
      } 
      // Add Size Of All Paths 
      enumerator = [contents objectEnumerator]; 
      while (path = [enumerator nextObject]) 
      { 
       NSDictionary * fattrs = [self attributesOfItemAtPath: [ source stringByAppendingPathComponent:path ] error:error]; 
       size += [[fattrs objectForKey:NSFileSize] unsignedLongLongValue]; 
      } 
      // Return Total Size in Bytes 

      return [ NSNumber numberWithUnsignedLongLong:size]; 
     } 

     @end 
0

希望這將有助於沙箱中使用該

- (unsigned long long) fastFolderSizeAtFSRef:(NSString *)theFilePath 
{ 
unsigned long long totalSize = 0; 
NSFileManager *fileManager = [NSFileManager defaultManager]; 
BOOL isdirectory; 
NSError *error; 

if ([fileManager fileExistsAtPath:theFilePath]) 
{ 


    NSMutableArray * directoryContents = [[fileManager contentsOfDirectoryAtPath:theFilePath error:&error] mutableCopy]; 


    for (NSString *fileName in directoryContents) 
    { 
     if (([fileName rangeOfString:@".DS_Store"].location != NSNotFound)) 
      continue; 



      NSString *path = [theFilePath stringByAppendingPathComponent:fileName]; 
      if([fileManager fileExistsAtPath:path isDirectory:&isdirectory] && isdirectory ) 
      { 

        totalSize = totalSize + [self fastFolderSizeAtFSRef:path]; 



      } 
      else 
      { 
       unsigned long long fileSize = [[fileManager attributesOfItemAtPath:path error:&error] fileSize]; 
       totalSize = totalSize + fileSize; 
      } 
    } 
} 
return totalSize; 
}