轻松获取文件夹大小(ObjC / Cocoa)?

时间:2009-08-14 01:37:25

标签: objective-c cocoa size directory nsfilemanager

现在我正在使用此代码来获取文件夹的大小:

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

问题在于其高度空洞。它要么增加几兆字节,要么从实际大小中扣除几兆字节。例如,我得到了一个.app包的文件大小,这个方法报告了16.2MB,而实际的是15.8。

获取文件夹大小的最佳方法是什么?

由于

7 个答案:

答案 0 :(得分:6)

我今天需要自己做这件事,并且我发现this post on the Cocoa-dev list中的代码超快,并且与Finder对字节的​​说法相匹配。 (不要忘记在kFSCatInfoRsrcSizes标志中使用OR,以便获得资源分叉大小!)

如果您需要有关如何使用它的更多说明,请发表评论,我将编辑此帖子。 =)

答案 1 :(得分:4)

fileSize的文档说明它不包括资源分叉的大小。您可能需要使用Carbon File Manager API来可靠地计算目录大小。

答案 2 :(得分:2)

我只是想对Dave DeLong关于Cocoa-dev帖子的建议,但添加一个注意事项,以确保阅读该帖子中的所有帖子。 Rosyna有一个特别值得注意的。在我的情况下,我遵循了这个建议(将每次获取的最大项目更改为40)并看到速度跳跃以及结束一个令人讨厌的崩溃错误。

答案 3 :(得分:2)

希望这会有所帮助

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

答案 4 :(得分:1)

这通常是如何完成的。 2种可能性:

  1. 检查您的字节 - >兆字节转换例程。此外,你想要兆字节还是mebibytes? (这可能取决于你将它与之进行比较。)

  2. 尝试为traverseLink参数传递NO。在捆绑中可能有一个符号链接指向您正在比较它的例程将不会考虑的其他内容。你要么在捆绑中计算两次,要么完全包括捆绑之外的东西(很可能是前者)。

答案 5 :(得分:1)

我知道这是一个古老的话题。但是那里的任何人都在寻找如何做到这一点的答案,

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

它将使用终端确定文件夹的大小(以字节为单位)。它将使用Cocoa内置的NSFileManager来获取文件的大小。它非常快,并且获得了发现者报告的确切大小。

答案 6 :(得分: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