2009-10-06 14 views
33

Esiste un metodo per ottenere il contenuto di una cartella in un ordine particolare? Mi piacerebbe una serie di dizionari degli attributi di file (o solo nomi di file) ordinati per data modificata.Ottieni il contenuto della directory in ordine modificato data

In questo momento, sto facendo in questo modo:

  • ottenere un array con i nomi dei file
  • ottenere gli attributi di ciascun file
  • negozio di percorso del file e la data di modifica in un dizionario con la data come chiave

Avanti Devo emettere il dizionario in ordine di data, ma mi chiedevo se c'è un modo più semplice? In caso contrario, c'è uno snippet di codice da qualche parte che farà questo per me?

Grazie.

risposta

35

codice di Nall sopra mi ha segnalato nella giusta direzione, ma Penso che ci siano alcuni errori nel codice come pubblicato sopra. Per esempio:

  1. Perché filesAndProperties assegnati utilizzando NMutableDictonary piuttosto che un NSMutableArray?

  2. 
    NSDictionary* properties = [[NSFileManager defaultManager] 
                 attributesOfItemAtPath:NSFileModificationDate 
                 error:&error]; 
    
    
    Il codice di cui sopra sta passando il parametro sbagliato per attributesOfItemAtPath - Va attributesOfItemAtPath:path

  3. Voi Ordinamento della matrice files, ma si dovrebbe essere di ordinamento filesAndProperties.


ho implementato lo stesso, con le correzioni, e l'utilizzo di blocchi e postato qui sotto:


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

+0

Per invertire l'ordine è possibile moltiplicare il risultato del confronto per -1. –

+5

Per invertire l'ordine è sufficiente utilizzare 'return [[path2 objectForKey: @" lastModDate "] compare: [percorso1 oggettoPerfetto: @" ultimoModDato "]];' – Ievgen

0

Il codice non funziona in iPhone SDK, pieno di errore di compilazione. Trova aggiornato il codice `

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

`

+0

Grazie per la risposta.Sembra che ci siano alcune cose che non funzioneranno con l'iPhone SDK qui (NSURLContentModificationDateKey e alcuni altri metodi NSURL). –

+0

Ho iniziato a provare a cambiarlo per funzionare con l'iPhone SDK, ma getResourceValue non esiste lì. Cercherò un ordinamento di array per iPhone. –

+0

nevan, l'ho aggiornato per funzionare all'interno dei limiti dell'iPhone SDK – nall

5

E 'troppo lento

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

provare questo codice:

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

Questo è molto più veloce. 4x più veloce nei miei test. Ho incontrato un bug con questo però. Il mio gmtime sta restituendo UTC non GMT. Alcune volte ha avuto una differenza di un'ora che ha causato problemi. –

+0

Regolare il codice come segue: NSCalendar * cal = [NSCalendar currentCalendar]; NSTimeZone * tz = [NSTimeZone timeZoneWithAbbreviazione: [[NSString alloc] initWithUTF8String: date-> tm_zone]]; cal.timeZone = tz; –

+0

È necessario #importare "sys/stat.h" –

10

più semplice ...

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]; 
}]; 
+0

cos'è path_thumb? – DJTano

19

Che ne dite di questo :

// 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]; 
         }]; 
+11

Stavo solo cercando la soluzione per questo e ho finito usando il codice di cui sopra. Quindi l'ho messo qui perché penso che sia più pulito di quello che altri hanno fornito;) –

Problemi correlati