Вопрос

Прямо сейчас я использую этот код, чтобы получить размер папки:

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,2 МБ, тогда как на самом деле это 15,8 МБ.

Как лучше всего узнать размер папки?

Спасибо

Это было полезно?

Решение

Мне нужно было сделать это сегодня самому, и я обнаружил, что код в этот пост в списке разработчиков Cocoa работает очень быстро и соответствует тому, что говорит Finder, байту.(не забудьте добавить ИЛИ к флагу kFSCatInfoRsrcSizes, чтобы вы также получили размеры ветвей ресурсов!)

Если вам нужно больше объяснений о том, как его использовать, просто оставьте комментарий, и я отредактирую этот пост."="

Другие советы

Документация для fileSize заявляет, что не включает размер ветки ресурса.Возможно, вам придется использовать API диспетчера файлов Carbon для надежного расчета размеров каталогов.

Я просто хотел поддержать предложение Дэйва ДеЛонга по поводу поста о Cocoa-dev, но добавить предостережение: обязательно прочитайте все сообщения в теме.Особенно стоит отметить одну работу Розины.В моем случае я последовал этому совету (изменив максимальное количество элементов за выборку на 40) и увидел скачок скорости, а также конец неприятной ошибки, приводящей к сбою.

надеюсь, это поможет

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

Обычно это делается именно так.2 возможности:

  1. Проверьте свои процедуры преобразования байт -> мегабайт.И еще, вам нужны мегабайты или мебибайты?(Вероятно, это зависит от того, с чем вы это сравниваете.)

  2. Попробуйте передать NO для traverseLink параметр.В пакете вполне может быть символическая ссылка, указывающая на что-то еще, что процедура, с которой вы ее сравниваете, не учитывает.Вы либо дважды учтете что-то в пакете, либо полностью включите что-то вне пакета (скорее всего, в первом случае).

Я знаю, что это старая тема.Но для тех, кто ищет ответы о том, как это сделать,

[[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 для получения размера файлов.Это очень быстро и получает точный размер, который сообщает Finder.

Этот код является расширением (категорией) класса 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top