2009-08-14 6 views
6

En este momento estoy usando este código para obtener el tamaño de una carpeta:¿Forma fácil de obtener el tamaño de la carpeta (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]; 

El problema es que su muy Incorrecto. Agrega algunos megabytes o deduce algunos megabytes del tamaño real. Por ejemplo, obtuve el tamaño de archivo de un paquete .app y este método reportó 16.2MB, mientras que el actual es 15.8.

¿Cuál es la mejor manera de obtener el tamaño de una carpeta?

Gracias

+0

Cualquiera que use este bajo Sandboxing? :-) –

Respuesta

5

Necesito hacer esto hoy mismo, y he encontrado que el código en this post on the Cocoa-dev list es super rápido y coincide con lo que Finder dice al byte. (¡no olvide O en el indicador kFSCatInfoRsrcSizes para obtener tamaños de horquillas de recursos también!)

Si necesita más explicaciones sobre cómo usarlo, simplemente deje un comentario y editaré esta publicación. =)

+0

Gracias, ¿cuál es una buena manera de convertir un NSString que contiene una ruta a un FSRef? Gracias – indragie

+0

Acabo de responder a su pregunta. =) –

+0

@Dave, este enlace está roto, ¿podrías actualizarlo o colocar el código para responder? – Igor

1

Normalmente esta es la forma en que se hace. 2 posibilidades:

  1. Revise sus rutinas de conversión byte -> megabyte. Además, ¿quieres megabytes o mebibytes? (Probablemente dependa de lo que esté comparando).

  2. Intente pasar NO para el parámetro traverseLink. Es muy posible que haya un enlace simbólico en el paquete que apunte a algo más que la rutina para la que lo está comparando no tendrá en cuenta. O bien contará algo en el paquete dos veces, o incluirá algo fuera del paquete por completo (muy probablemente el primero).

4

La documentación para fileSize afirma que no incluye el tamaño de un tenedor de recursos. Es posible que necesite utilizar Carbon File Manager API para calcular de manera confiable los tamaños de los directorios.

+0

Ah sí, esa es otra posibilidad. Me olvide de eso. – kperryua

2

Solo quería secundar la sugerencia de Dave DeLong sobre la publicación en Cocoa-dev, pero agregue una nota de advertencia para asegurarse de leer todas las publicaciones en el hilo. Hay uno de Rosyna que vale la pena destacar. En mi caso, seguí ese consejo (cambiando los artículos máximos por búsqueda a 40) y vi un salto de velocidad así como el final de un desagradable error de colisión.

+1

Sería mejor agregar esto como un comentario a su respuesta para que permanezcan relacionados aunque cambien sus posiciones en la página. –

+0

Tengo problemas con el método de Dave DeLong. Uso este código para convertir mi NSString en un 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} Y entonces trato de ejecutar el método: [auto fastFolderSizeAtFSRef: f]; Sin embargo me sale el error "tipo incompatible para el argumento 1 de 'fastFolderSize'" ¿Alguna idea? Gracias – indragie

2

Sé que este es un tema antiguo. Pero para alguien por ahí en busca de respuestas sobre cómo hacer esto,

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

Se utilizará el terminal para determinar un tamaño de carpetas en bytes. Y usará Cocoa's built in NSFileManager para obtener el tamaño de los archivos. Es muy rápido y obtiene el tamaño exacto que reporta el buscador.

+0

, aunque esto funcionará, tiene el impacto en el rendimiento de crear otro proceso (que puede ser bastante caro) o utilizar 'NSFileManager', que no incluye recursos de información al calcular los tamaños. –

1

Este código es como extensión (categoría) de la clase NSFileManager. Suma los tamaños de todo el contenido de la carpeta. Tenga en cuenta que el tratamiento de error podría mejorarse.

@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

esperanza que esto ayudará

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