获取文件夹大小的简单方法(ObjC/Cocoa)?

问题描述 投票:0回答:7

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

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。

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

谢谢

objective-c cocoa size directory nsfilemanager
7个回答
7
投票

我今天需要自己做这件事,并且我发现Cocoa-dev 列表上的这篇文章中的代码非常快并且与 Finder 对字节所说的内容相匹配。 (不要忘记在 kFSCatInfoRsrcSizes 标志中使用 OR,这样您也可以获得资源分叉大小!)

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


4
投票

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


2
投票

我只是想赞同 Dave DeLong 关于 Cocoa-dev 上的帖子的建议,但添加一个警告注释以确保阅读该线程中的所有帖子。 Rosyna 的一个作品特别值得注意。就我而言,我遵循了该建议(将每次获取的最大项目更改为 40),并看到了速度的跳跃以及令人讨厌的崩溃错误的结束。


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

1
投票

这就是通常的做法。 2种可能性:

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

  2. 尝试为

    traverseLink
    参数传递 NO。捆绑包中很可能有一个符号链接指向您与之比较的例程无法解释的其他内容。您要么将捆绑包中的某些内容计算两次,要么将完全包含在捆绑包之外的某些内容(很可能是前者)。


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 来获取文件的大小。它的速度非常快,并且可以获取取景器报告的准确尺寸。


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
© www.soinside.com 2019 - 2024. All rights reserved.