3

NSFileManagerのメソッドを使用してenumeratorAtPath、特定のディレクトリの下のファイルサイズを計算しています。

NSString *iterDir = @"/path/to/dir/";
NSFileManager *fm = [[NSFileManager alloc] init];
NSDirectoryEnumerator *dirEnum = [fm enumeratorAtPath:iterDir];

NSString *file;
BOOL isDir;
long long fileSize = 0;
while (file = [dirEnum nextObject]) {
    @autoreleasepool {
        file = [iterDir stringByAppendingString:file];
        if ([fm fileExistsAtPath:file isDirectory:&isDir]) {
            if (!isDir) {
                NSError *error;
                NSDictionary *attributes = [fm attributesOfItemAtPath:file error:&error];
                if (!error) {
                    fileSize += [attributes[@"NSFileSize"] doubleValue];
                }
            }
        }
    }
}
NSLog(@"fileSize:%lld", fileSize);

結果は次のようになります。

whileループ中に多くのメモリを消費します

時々このように:

記憶が戻らない

メモリは何に使われていますか?@autoreleasepoolなぜ外部に追加しても効果がないのですか?

4

1 に答える 1

1

有効なディレクトリ パスに置き換えても、サンプルを提供どおりに実行できませんでした。あなたのコードにはいくつかの問題があります。ここでは、いくつかの変更を加える必要があります。1つはこの行です:

file = [iterDir stringByAppendingString:file];

これは実際には次のように変更する必要があります:

file = [iterDir stringByAppendingPathComponent:file];

後者は、ディレクトリパスが a で終わるかどうかに関係なく、パスを正しく追加するため、はるかに安全です/。(以前はディレクトリパスを取得していたため、元のファイルは私の場合は失敗しました[@"~/Desktop" stringByExpandingTildeInPath]。これにより、末尾のないパスが生成され/ます。)

次に、ループ内で、初期化されていない変数errorをスタックに割り当て、それを参照渡ししてから、それがnil. errorメソッドが nil (またはメソッドによっては ) を返さない限り、 の値は保証されないため、これは間違った質問NOです。attributes代わりに、 if isを尋ね、fornilを渡す必要があります。それ以外の場合は興味がないようです。要約すると、これを変更します。NULLerror

NSError *error;
NSDictionary *attributes = [fm attributesOfItemAtPath:file error:&error];
if (!error) {

これに:

NSDictionary *attributes = [fm attributesOfItemAtPath:file error:NULL];
if (attributes != nil) {

その 2 番目の問題を修正すると、結果の一貫性が向上することを約束します。NSLog()一方、コードを実行すると、ステートメントで有効な値のように見える結果が得られます。

当然のことながら、ループに高速列挙を使用することもできます。それ以外の:

while (file = [dirEnum nextObject]) {

代わりに次を使用できます。

for (file in dirEnum) {

元の質問に進みます。割り当てられたメモリが増大する理由は、ファイル名を含む文字列が@autoreleasepoolディレクティブの範囲外でメインの自動解放プールに割り当てられ、そのプールが空になるまでそこに留まるためです。ただし、ループ内で独自の自動解放プールを使用して、まだ良いことをしています。

于 2013-07-09T04:38:15.500 に答える