【问题标题】:Get directory contents in date modified order按日期修改顺序获取目录内容
【发布时间】:2010-12-04 04:09:12
【问题描述】:

有没有按特定顺序获取文件夹内容的方法?我想要一个按修改日期排序的文件属性字典(或只是文件名)数组。

现在,我正在这样做:

  • 获取包含文件名的数组
  • 获取每个文件的属性
  • 将文件的路径和修改日期存储在字典中,以日期为键

接下来我必须按日期顺序输出字典,但我想知道是否有更简单的方法?如果没有,是否有代码 sn-p 可以为我执行此操作?

谢谢。

【问题讨论】:

  • “我想知道是否有更简单的方法?”通读答案,我认为答案是否定的,对吧?

标签: iphone objective-c nsfilemanager


【解决方案1】:

这个怎么样:

// Application documents directory
NSURL *documentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];

NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:documentsURL
                                                          includingPropertiesForKeys:@[NSURLContentModificationDateKey]
                                                                             options:NSDirectoryEnumerationSkipsHiddenFiles
                                                                               error:nil];

NSArray *sortedContent = [directoryContent sortedArrayUsingComparator:
                        ^(NSURL *file1, NSURL *file2)
                        {
                            // compare
                            NSDate *file1Date;
                            [file1 getResourceValue:&file1Date forKey:NSURLContentModificationDateKey error:nil];

                            NSDate *file2Date;
                            [file2 getResourceValue:&file2Date forKey:NSURLContentModificationDateKey error:nil];

                            // Ascending:
                            return [file1Date compare: file2Date];
                            // Descending:
                            //return [file2Date compare: file1Date];
                        }];

【讨论】:

  • 我自己只是在寻找解决方案,最终使用了上面的代码。所以我把它放在这里是因为我认为它比其他人提供的更干净;)
【解决方案2】:

更简单...

NSArray*  filelist_sorted;
filelist_sorted = [filelist_raw sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    NSDictionary* first_properties  = [[NSFileManager defaultManager] attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@", path_thumb, obj1] error:nil];
    NSDate*       first             = [first_properties  objectForKey:NSFileModificationDate];
    NSDictionary* second_properties = [[NSFileManager defaultManager] attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@", path_thumb, obj2] error:nil];
    NSDate*       second            = [second_properties objectForKey:NSFileModificationDate];
    return [second compare:first];
}];

【讨论】:

  • 什么是 path_thumb ?
【解决方案3】:

太慢了

[[NSFileManager defaultManager]
                                attributesOfItemAtPath:NSFileModificationDate
                                error:&error];

试试这个代码:

+ (NSDate*) getModificationDateForFileAtPath:(NSString*)path {
    struct tm* date; // create a time structure
    struct stat attrib; // create a file attribute structure

    stat([path UTF8String], &attrib);   // get the attributes of afile.txt

    date = gmtime(&(attrib.st_mtime));  // Get the last modified time and put it into the time structure

    NSDateComponents *comps = [[NSDateComponents alloc] init];
    [comps setSecond:   date->tm_sec];
    [comps setMinute:   date->tm_min];
    [comps setHour:     date->tm_hour];
    [comps setDay:      date->tm_mday];
    [comps setMonth:    date->tm_mon + 1];
    [comps setYear:     date->tm_year + 1900];

    NSCalendar *cal = [NSCalendar currentCalendar];
    NSDate *modificationDate = [[cal dateFromComponents:comps] addTimeInterval:[[NSTimeZone systemTimeZone] secondsFromGMT]];

    [comps release];

    return modificationDate;
}

【讨论】:

  • 这要快得多。在我的测试中快 4 倍。不过,我遇到了一个错误。我的 gmtime 返回的是 UTC 而不是 GMT。有时会有一小时的差异,这会导致问题。
  • 调整代码如下: NSCalendar *cal = [NSCalendar currentCalendar]; NSTimeZone *tz = [NSTimeZone timeZoneWithAbbreviation:[[NSString alloc] initWithUTF8String:date->tm_zone]]; cal.timeZone = tz;
  • 你需要#import "sys/stat.h"
【解决方案4】:

代码在 iPhone SDK 中不起作用,充满了编译错误。请找到更新的代码 `

NSInteger lastModifiedSort(id path1, id path2, void* context)
{
    int comp = [[path1 objectForKey:@"lastModDate"] compare:
     [path2 objectForKey:@"lastModDate"]];
    return comp;
}

-(NSArray *)filesByModDate:(NSString*) path{

    NSError* error = nil;

    NSArray* filesArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path
                                                                         error:&error];
    if(error == nil)
    {
        NSMutableArray* filesAndProperties = [NSMutableArray arrayWithCapacity:[filesArray count]];

        for(NSString* imgName in filesArray)
        {

            NSString *imgPath = [NSString stringWithFormat:@"%@/%@",path,imgName];
            NSDictionary* properties = [[NSFileManager defaultManager]
                                        attributesOfItemAtPath:imgPath
                                        error:&error];

            NSDate* modDate = [properties objectForKey:NSFileModificationDate];

            if(error == nil)
            {
                [filesAndProperties addObject:[NSDictionary dictionaryWithObjectsAndKeys:
                                               imgName, @"path",
                                               modDate, @"lastModDate",
                                               nil]];                     
            }else{
                NSLog(@"%@",[error description]);
            }
        }
        NSArray* sortedFiles = [filesAndProperties sortedArrayUsingFunction:&lastModifiedSort context:nil];

        NSLog(@"sortedFiles: %@", sortedFiles);      
        return sortedFiles;
    }
    else
    {
        NSLog(@"Encountered error while accessing contents of %@: %@", path, error);
    }

    return filesArray;
}

`

【讨论】:

  • 感谢您的回答。这里似乎有一些东西不适用于 iPhone SDK(NSURLContentModificationDateKey 和其他一些 NSURL 方法)。
  • 我已经开始尝试将其更改为与 iPhone SDK 一起使用,但那里不存在 getResourceValue。我会为 iPhone 寻找一个数组排序。
  • nevan,我更新了它以在 iPhone SDK 的约束下工作
  • 这段代码中有很多小错误......我认为这段代码没有在 iOS 上测试过。
【解决方案5】:

以上纳尔的代码为我指明了正确的方向,但我认为上面发布的代码存在一些错误。例如:

  1. 为什么filesAndProperties 分配使用NMutableDictonary 而不是NSMutableArray

  2. 
    NSDictionary* properties = [[NSFileManager defaultManager]
                                            attributesOfItemAtPath:NSFileModificationDate
                                            error:&error];
    
    
    上面的代码为 attributesOfItemAtPath 传递了错误的参数 - 它应该是 attributesOfItemAtPath:path

  3. 您正在对files 数组进行排序,但您应该对filesAndProperties 进行排序。


我已经实现了相同的功能,并进行了更正,并使用了块并发布在下面:


    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString* documentsPath = [searchPaths objectAtIndex: 0]; 

    NSError* error = nil;
    NSArray* filesArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsPath error:&error];
    if(error != nil) {
        NSLog(@"Error in reading files: %@", [error localizedDescription]);
        return;
    }

    // sort by creation date
    NSMutableArray* filesAndProperties = [NSMutableArray arrayWithCapacity:[filesArray count]];
    for(NSString* file in filesArray) {
        NSString* filePath = [iMgr.documentsPath stringByAppendingPathComponent:file];
        NSDictionary* properties = [[NSFileManager defaultManager]
                                    attributesOfItemAtPath:filePath
                                    error:&error];
        NSDate* modDate = [properties objectForKey:NSFileModificationDate];

        if(error == nil)
        {
            [filesAndProperties addObject:[NSDictionary dictionaryWithObjectsAndKeys:
                                           file, @"path",
                                           modDate, @"lastModDate",
                                           nil]];                 
        }
    }

        // sort using a block
        // order inverted as we want latest date first
    NSArray* sortedFiles = [filesAndProperties sortedArrayUsingComparator:
                            ^(id path1, id path2)
                            {                               
                                // compare 
                                NSComparisonResult comp = [[path1 objectForKey:@"lastModDate"] compare:
                                                           [path2 objectForKey:@"lastModDate"]];
                                // invert ordering
                                if (comp == NSOrderedDescending) {
                                    comp = NSOrderedAscending;
                                }
                                else if(comp == NSOrderedAscending){
                                    comp = NSOrderedDescending;
                                }
                                return comp;                                
                            }];

【讨论】:

  • 要反转排序,您只需将比较结果乘以 -1。
  • 要反转排序,您可以使用return [[path2 objectForKey:@"lastModDate"] compare:[path1 objectForKey:@"lastModDate"]];
猜你喜欢
  • 2017-04-15
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多