2010-12-27 2 views
2

J'essaie de trouver un moyen d'afficher la progression actuelle ainsi que le temps restant pour décompresser et écrire le contenu d'un fichier zip sur le disque. J'utilise actuellement la classe ZipArchiver trouvée ici http://code.google.com/p/ziparchive/ qui fonctionne très bien. Le problème est que beaucoup de celui-ci est écrit en C++ que je n'avez pas trop d'expérience dans Voici la fonction correspondante.Comment afficher le fichier décompresser la progression?

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

Je suis un moment difficile essayer de comprendre comment je serais en mesure de insérer un code qui me permettrait d'afficher le pourcentage actuel de progression ainsi que le temps restant pour décompresser et écrire tous les fichiers sur le disque. Des idées sur la façon dont je pourrais y arriver?

thx

+1

Un commentaire de style qui n'a rien à voir avec votre problème: Il semble que vous nommer vos méthodes avec des lettres majuscules (-UnzipFileTo: remplacer: , -OutputErrorMessage :, et ainsi de suite). Ne fais pas ça, ce n'est pas le bon style pour Cocoa. –

+0

J'ai supprimé les balises Objective-C et C++ car il ne s'agit pas d'une question sur l'une ou l'autre langue, mais plutôt sur l'utilisation d'une API. –

Répondre

0

Ceci est l'équation que vous utilisez pour estimer le temps restant:

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

timeTaken:

Le nombre de secondes écoulées depuis le début du processus. Vous pouvez utiliser NSTimeInterval et les fonctions NSDate pour obtenir ce résultat. En ce qui concerne le pourcentage, vous ne pouvez voir que le pourcentage de fichiers traités, mais pas la progression d'un décompression en cours.

+0

Pourquoi ne pas vérifier la taille compressée/non compressée au lieu du nombre de fichiers? – user1283704

3

Ne pas "insérer du code pour afficher la progression." Au lieu de cela, effectuez le travail réel dans une opération distincte et faites en communiquer la progression au thread principal pour présentation à l'utilisateur.

En lisant votre code, il y a quelques endroits extrêmement évidents pour transmettre cette information. Par exemple, il y a une boucle interne qui lit les données d'un seul fichier dans l'archive, et il y a une boucle externe qui itère sur les fichiers dans l'archive. Vous pouvez facilement créer un ensemble de messages de délégué qui peuvent être utilisés pour signaler quel fichier est en cours d'extraction, à quelle distance il se trouve et à quelle distance de l'archive entière se trouve l'extraction.

Ensuite, vous pouvez créer un délégué spécifique qui sait comment interagir avec votre interface utilisateur (sur le thread principal) et présenter cette progression à l'utilisateur.

1

Utilisation:

https://github.com/mattconnolly/ZipArchive

ou de cocoapods:

pod 'ZipArchive', '1.1.0'

il suffit de créer un bloc de progrès assigner à votre variable zip et laissez le nslog vous montrer.

facile ...

Utilisation:

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