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

发布于 2024-08-02 09:27:27 字数 625 浏览 2 评论 0原文

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

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。

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

谢谢

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.

What's the best way to get the size of a folder?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

不羁少年 2024-08-09 09:27:27

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

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

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. (don't forget to OR in the kFSCatInfoRsrcSizes flag so you get resource fork sizes, too!)

If you need more explanation on how to use it, just leave a comment and I'll edit this post. =)

薄荷港 2024-08-09 09:27:27

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

The documentation for fileSize states it does not include the size of a resource fork. You may need to use the Carbon File Manager API to reliably calculate directory sizes.

山田美奈子 2024-08-09 09:27:27

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

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. There is one by Rosyna that's particularly worth noting. 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.

離殇 2024-08-09 09:27:27

希望这会有所帮助

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

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;
}
雪花飘飘的天空 2024-08-09 09:27:27

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

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

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

This is typically how it is done. 2 possibilities:

  1. Check your byte -> megabyte conversion routines. Also, do you want megabytes or mebibytes? (It probably depends on what you're comparing it to.)

  2. Try passing NO for the traverseLink parameter. 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).

花开半夏魅人心 2024-08-09 09:27:27

我知道这是一个老话题了。但对于任何正在寻找如何执行此操作的答案的人来说,

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

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. It's very fast, and gets the exact size that finder reports.

爱要勇敢去追 2024-08-09 09:27:27

此代码作为 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

This code is as extension(category) to the NSFileManager class. 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文