2009-08-14 5 views
6

Сейчас я использую этот код, чтобы получить размер папки:Простой способ получить размер папки (ObjC/Cocoa)?

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.

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

Thanks

+0

Любой, кто использует это под песочниц? :-) –

ответ

5

Мне нужно было сделать это сегодня, и я обнаружил, что код в this post on the Cocoa-dev list очень быстрый и соответствует тому, что Finder говорит байту. (не забудьте OR в флагом kFSCatInfoRsrcSizes, чтобы вы тоже получили размеры вилочных ресурсов!)

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

+0

Спасибо, что это хороший способ конвертировать NSString, содержащий путь к FSRef? Спасибо – indragie

+0

Просто ответил на ваш вопрос. =) –

+0

@Dave, эта ссылка не работает, вы можете ее обновить или разместить код, чтобы ответить? – Igor

1

Как правило, это делается. 2 возможности:

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

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

4

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

+0

Ах да, это еще одна возможность. Я забыл об этом. – kperryua

2

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

+1

Может быть, лучше добавить это в качестве комментария к его ответу, чтобы они оставались связанными, даже когда их позиции на странице менялись. –

+0

У меня проблемы с методом Дейва ДеЛонга. Я использую этот код для преобразования моего NSString в FSRef: FSRef f; \t \t OSStatus os_status = FSPathMakeRef ((const UInt8 *) [filePath fileSystemRepresentation], & f, NULL); \t \t if (os_status == noErr) { \t \t \t NSLog (@ "Success"); \t \t} И тогда я пытаюсь запустить метод: [само fastFolderSizeAtFSRef: F]; Однако я получаю ошибку «несовместимый тип для аргумента 1 из« fastFolderSize »» Любые идеи? Спасибо – indragie

2

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

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

+0

, в то время как это, безусловно, будет работать, у вас есть успех при создании другого процесса (который может быть довольно дорогим) или с использованием '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 
0

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

- (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; 
} 
Смежные вопросы