简体   繁体   English

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

[英]Easy way to get size of folder (ObjC/Cocoa)?

Right now I'm using this code to get the size of a folder: 现在我正在使用此代码来获取文件夹的大小:

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

The problem is that its highly innacurate. 问题是它非常真实。 It either adds a few megabytes or deducts a few megabytes from the actual size. 它要么增加几兆字节,要么从实际大小中扣除几兆字节。 For example I got the file size of an .app bundle and this method reported 16.2MB, whereas the actual thing is 15.8. 例如,我得到了一个.app包的文件大小,这个方法报告了16.2MB,而实际的是15.8。

What's the best way to get the size of a folder? 获取文件夹大小的最佳方法是什么?

Thanks 谢谢

I needed to do this today myself, and I've found that the code in this post on the Cocoa-dev list is super fast and matches what Finder says to the byte. 我今天需要自己做这个,并且我发现Cocoa-dev列表这篇文章中的代码非常快,并且匹配Finder对字节所说的内容。 (don't forget to OR in the kFSCatInfoRsrcSizes flag so you get resource fork sizes, too!) (不要忘记在kFSCatInfoRsrcSizes标志中使用OR,这样你也可以获得资源分叉大小!)

If you need more explanation on how to use it, just leave a comment and I'll edit this post. 如果您需要有关如何使用它的更多解释,请发表评论,我将编辑此帖。 =) =)

The documentation for fileSize states it does not include the size of a resource fork. fileSize的文档声明它不包括资源fork的大小。 You may need to use the Carbon File Manager API to reliably calculate directory sizes. 您可能需要使用Carbon File Manager API来可靠地计算目录大小。

I just wanted to second Dave DeLong's suggestion about the post on Cocoa-dev, but add a cautionary note to be sure to read all the posts in the thread. 我只是想对Dave DeLong关于Cocoa-dev上的帖子的建议,但添加一个注意事项,以确保阅读线程中的所有帖子。 There is one by Rosyna that's particularly worth noting. Rosyna有一个特别值得注意的。 In my case I followed that advice (changing max items per fetch to 40) and saw a speed jump as well as the end to a nasty crashing bug. 在我的情况下,我遵循了这个建议(将每次获取的最大项目更改为40)并看到速度跳跃以及结束一个令人讨厌的崩溃错误。

hope this will help 希望这会有所帮助

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

This is typically how it is done. 这通常是如何完成的。 2 possibilities: 2种可能性:

  1. Check your byte -> megabyte conversion routines. 检查你的字节 - >兆字节转换例程。 Also, do you want megabytes or mebibytes? 此外,你想要兆字节还是mebibytes? (It probably depends on what you're comparing it to.) (这可能取决于你要比较的东西。)

  2. Try passing NO for the traverseLink parameter. 尝试为traverseLink参数传递NO。 There might very well be a symlink in the bundle pointing to something else that the routine you're comparing it to won't account for. 在捆绑中可能有一个符号链接指向您正在比较它的例程将不会考虑的其他内容。 You'll either count something in the bundle twice, or you'll include something outside the bundle entirely (most likely the former). 你要么在捆绑中计算两次,要么完全包括捆绑之外的东西(很可能是前者)。

This code is as extension(category) to the NSFileManager class. 此代码作为NSFileManager类的扩展(类别)。 It sums the sizes of all folder content. 它汇总了所有文件夹内容的大小。 Note that error treatment could be enhanced. 请注意,可以增强错误处理。

 @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

I know that this is an old topic. 我知道这是一个古老的话题。 But for anyone out there looking for answers on how to do this, 但对于那里的任何人寻找如何做到这一点的答案,

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

It will use terminal to determine a size for folders in bytes. 它将使用终端来确定文件夹的大小(以字节为单位)。 And it will use Cocoa's built in NSFileManager to get the size of files. 它将使用Cocoa内置的NSFileManager来获取文件的大小。 It's very fast, and gets the exact size that finder reports. 它非常快,并且获得了finder报告的确切大小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM