2010-12-27 19 views
2

Ich versuche einen Weg zu finden, um den aktuellen Fortschritt sowie die verbleibende Zeit zum Entpacken und Schreiben des Inhalts einer Zip-Datei auf die Festplatte anzuzeigen. Ich verwende derzeit die ZipArchiver-Klasse, die hier gefunden wird http://code.google.com/p/ziparchive/, die ziemlich gut funktioniert. Das Problem ist, dass viele es in C++ geschrieben ist, die ich in zu viel Erfahrung nicht, hier ist die entsprechende Funktion.Wie wird der Fortschritt der Dateientpackung angezeigt?

-(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite 
{ 
    BOOL success = YES; 
    int ret = unzGoToFirstFile(_unzFile); 
    unsigned char   buffer[4096] = {0}; 
    NSFileManager* fman = [NSFileManager defaultManager]; 
    if(ret!=UNZ_OK) 
    { 
      [self OutputErrorMessage:@"Failed"]; 
    } 

    do{ 
      if([_password length]==0) 
        ret = unzOpenCurrentFile(_unzFile); 
      else 
        ret = unzOpenCurrentFilePassword(_unzFile, [_password cStringUsingEncoding:NSASCIIStringEncoding]); 
      if(ret!=UNZ_OK) 
      { 
        [self OutputErrorMessage:@"Error occurs"]; 
        success = NO; 
        break; 
      } 
      // reading data and write to file 
      int read ; 
      unz_file_info fileInfo ={0}; 
      ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); 
      if(ret!=UNZ_OK) 
      { 
        [self OutputErrorMessage:@"Error occurs while getting file info"]; 
        success = NO; 
        unzCloseCurrentFile(_unzFile); 
        break; 
      } 
      char* filename = (char*) malloc(fileInfo.size_filename +1); 
      unzGetCurrentFileInfo(_unzFile, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0); 
      filename[fileInfo.size_filename] = '\0'; 

      // check if it contains directory 
      NSString * strPath = [NSString stringWithCString:filename]; 
      BOOL isDirectory = NO; 
      if(filename[fileInfo.size_filename-1]=='/' || filename[fileInfo.size_filename-1]=='\\') 
        isDirectory = YES; 
      free(filename); 
      if([strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location!=NSNotFound) 
      {// contains a path 
        strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]; 
      } 
      NSString* fullPath = [path stringByAppendingPathComponent:strPath]; 

      if(isDirectory) 
        [fman createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:nil error:nil]; 
      else 
        [fman createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; 
      if([fman fileExistsAtPath:fullPath] && !isDirectory && !overwrite) 
      { 
        if(![self OverWrite:fullPath]) 
        { 
          unzCloseCurrentFile(_unzFile); 
          ret = unzGoToNextFile(_unzFile); 
          continue; 
        } 
      } 
      FILE* fp = fopen((const char*)[fullPath UTF8String], "wb"); 
      while(fp) 
      { 
        read=unzReadCurrentFile(_unzFile, buffer, 4096); 
        if(read > 0) 
        { 
          fwrite(buffer, read, 1, fp); 
        } 
        else if(read<0) 
        { 
          [self OutputErrorMessage:@"Failed to reading zip file"]; 
          break; 
        } 
        else 
          break;       
      } 
      if(fp) 
      { 
        fclose(fp); 
        // set the orignal datetime property 
        NSDate* orgDate = nil; 

        //{{ thanks to brad.eaton for the solution 
        NSDateComponents *dc = [[NSDateComponents alloc] init]; 

        dc.second = fileInfo.tmu_date.tm_sec; 
        dc.minute = fileInfo.tmu_date.tm_min; 
        dc.hour = fileInfo.tmu_date.tm_hour; 
        dc.day = fileInfo.tmu_date.tm_mday; 
        dc.month = fileInfo.tmu_date.tm_mon+1; 
        dc.year = fileInfo.tmu_date.tm_year; 

        NSCalendar *gregorian = [[NSCalendar alloc] 
                    initWithCalendarIdentifier:NSGregorianCalendar]; 

        orgDate = [gregorian dateFromComponents:dc] ; 
        [dc release]; 
        [gregorian release]; 
        //}} 


        NSDictionary* attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate]; //[[NSFileManager defaultManager] fileAttributesAtPath:fullPath traverseLink:YES]; 
        if(attr) 
        { 
          //    [attr setValue:orgDate forKey:NSFileCreationDate]; 
          if(![[NSFileManager defaultManager] setAttributes:attr ofItemAtPath:fullPath error:nil]) 
          { 
            // cann't set attributes 
            NSLog(@"Failed to set attributes"); 
          } 

        } 



      } 
      unzCloseCurrentFile(_unzFile); 
      ret = unzGoToNextFile(_unzFile); 
    }while(ret==UNZ_OK && UNZ_OK!=UNZ_END_OF_LIST_OF_FILE); 
    return success; 
} 

Ich bin eine harte Zeit versucht, herauszufinden, wie ich in der Lage wäre, Fügen Sie einen Code ein, mit dem ich den aktuellen Fortschritt in Prozent sowie die verbleibende Zeit für das Entpacken und Schreiben aller Dateien auf die Festplatte anzeigen kann. Irgendwelche Ideen, wie ich das erreichen könnte?

thx

+1

Ein Stil Kommentar, der nichts mit dem Thema zu tun hat: Es sieht aus wie Sie Ihre Methoden mit Großbuchstaben (-UnzipFileTo Benennung: überschreiben: , -OutputErrorMessage :, und so weiter). Tun Sie das nicht, das ist kein richtiger Stil für Cocoa. –

+0

Ich habe die Objective-C- und C++ - Tags entfernt, da es sich hierbei nicht um eine der beiden Sprachen handelt, sondern um die Verwendung einer API. –

Antwort

0

Dies ist die Gleichung Sie die Zeit zu schätzen verwenden verbleibenden:

([time]/[NumberOfFilesProcessed]) * [NumberOfFilesRemaining] = EstTimeRemaining

time:

Die Anzahl der seit dem Start des Prozesses verstrichenen Sekunden. Sie können NSTimeInterval und die NSDate-Funktionen verwenden, um dieses Ergebnis zu erhalten.

Wie Prozentsatz, können Sie nur den Prozentsatz der verarbeiteten Dateien anzeigen, aber nicht den Fortschritt eines aktuellen unzip.

+0

Warum überprüfen Sie nicht die komprimierte/unkomprimierte Größe statt der Anzahl der Dateien? – user1283704

3

Fügen Sie keinen Code ein, um den Fortschritt anzuzeigen. Führen Sie stattdessen die eigentliche Arbeit in einer separaten Operation aus, und kommunizieren Sie ihren Fortschritt im Hauptthread für die Präsentation für den Benutzer.

Wenn Sie nur Ihren Code durchlesen, gibt es einige sehr offensichtliche Orte, an denen Sie diese Informationen weitergeben können. Zum Beispiel gibt es eine innere Schleife, die Daten aus einer einzelnen Datei im Archiv liest, und es gibt eine äußere Schleife, die über die Dateien im Archiv iteriert. Sie könnten einfach eine Reihe von Delegat-Nachrichten erstellen, die verwendet werden können, um zu melden, welche Datei extrahiert wird, wie weit diese entfernt ist und wie weit die Extraktion im gesamten Archiv erfolgt.

Dann können Sie einen bestimmten Delegaten erstellen, der weiß, wie er mit Ihrer Benutzeroberfläche (im Hauptthread) interagieren und diesen Fortschritt dem Benutzer präsentieren kann.

1

Verwendung:

https://github.com/mattconnolly/ZipArchive

oder von cocoapods:

pod 'ZipArchive', '1.1.0'

Nur ein Block von Fortschritt es zu einem Zip-Variable erstellen zuweisen und lass das nslog dir zeigen.

einfache ...

Verwendung:

ZipArchive *zip = [[ZipArchive alloc] init]; 

ZipArchiveProgressUpdateBlock progressBlock =^(int percentage, int filesProcessed, int numFiles) { 
    NSLog(@"total %d, filesProcessed %d of %d", percentage, filesProcessed, numFiles); 
}; 

zip.progressBlock = progressBlock; 

//open file 
[zip UnzipOpenFile:path]; 

//unzip file to 
[zip UnzipFileTo:contentPath overWrite:YES]; 
Verwandte Themen