2009-08-14 42 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; 
}