Question

En ce moment je suis en utilisant ce code pour obtenir la taille d'un dossier:

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

Le problème est que sa très innacurate. Il ajoute soit quelques méga-octets ou quelques méga-octets déduit de la taille réelle. Par exemple, je suis la taille du fichier d'un faisceau de .app et cette méthode 16.2MB signalé, alors que la chose réelle est de 15,8.

Quelle est la meilleure façon d'obtenir la taille d'un dossier?

Merci

Était-ce utile?

La solution

Je devais faire aujourd'hui moi-même, et je l'ai trouvé que le code ce post sur la liste Cocoa-dev est super rapide et correspond à ce que Finder dit à l'octet. (Ne pas oublier de OU dans le drapeau de kFSCatInfoRsrcSizes de sorte que vous obtenez la taille des fourches de ressources, aussi!)

Si vous avez besoin d'explications sur la façon de l'utiliser, il suffit de laisser un commentaire et je vais modifier ce poste. =)

Autres conseils

espère que cela aidera

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

Ceci est généralement la façon dont il est fait. 2 possibilités:

  1. Vérifiez votre octet -> routines de conversion méga-octets. En outre, vous voulez méga-octets ou mebibytes? (Cela dépend probablement de ce que vous comparez à.)

  2. Essayez de passer NO pour le paramètre traverseLink. Il pourrait très bien être un lien symbolique dans le faisceau pointant vers quelque chose d'autre que la routine vous comparez à ne comptabilisera pas. Vous aurez soit deux fois compter quelque chose dans le paquet, ou vous allez inclure entièrement quelque chose en dehors du faisceau (très probablement l'ancien).

Je sais que c'est un vieux sujet. Mais pour tout le monde là-bas chercher des réponses sur la façon de ce faire,

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

Il utilisera la borne pour déterminer une taille pour les dossiers en octets. Et il utilisera pour obtenir la taille des fichiers de Cocoa construit en NSFileManager. Il est très rapide, et obtient la taille exacte que finder rapports.

Ce code est comme extension (catégorie) à la classe NSFileManager. Il résume les tailles de tout le contenu du dossier.  Notez que le traitement d'erreur pourrait être améliorée.

 @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
scroll top