Domanda

Davvero bloccato nel tentativo di scrivere codice per decomprimere un file o una directory su iPhone.

Di seguito è riportato un codice di esempio che sto usando per provare a decomprimere un semplice file di testo.

Decomprime il file ma è danneggiato.

(void)loadView {

    NSString *DOCUMENTS_FOLDER = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    NSString *path = [DOCUMENTS_FOLDER stringByAppendingPathComponent:@"sample.zip"];

    NSString *unzipeddest = [DOCUMENTS_FOLDER stringByAppendingPathComponent:@"test.txt"];  

    gzFile file = gzopen([path UTF8String], "rb");

    FILE *dest = fopen([unzipeddest UTF8String], "w");

    unsigned char buffer[CHUNK];

    int uncompressedLength = gzread(file, buffer, CHUNK);

    if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength ||     ferror(dest)) {
        NSLog(@"error writing data");
    }
    else{

    }

    fclose(dest);
    gzclose(file);  
}
È stato utile?

Soluzione

Ha " sample.zip " è stato davvero creato con gZip? L'estensione .zip viene generalmente utilizzata per gli archivi creati da WinZip. Questi possono anche essere decompressi usando zLib, ma dovresti analizzare l'intestazione e usare altre routine.

Per verificare, dai un'occhiata ai primi due byte del file. Se è "PK", è WinZip, se è 0x1F8B, è gZip.

Poiché questo è specifico per iPhone, dai un'occhiata a questo Discussione sul forum SDK per iPhone in cui è menzionato miniZip . Sembra che questo possa gestire i file WinZip.

Ma se è davvero un file WinZip, dovresti dare un'occhiata alle Specifiche WinZip e prova ad analizzare il file da solo. Fondamentalmente dovrebbe analizzare alcuni valori di intestazione, cercare la posizione del flusso compresso e utilizzare le routine zLib per decomprimerlo.

Altri suggerimenti

Volevo una soluzione semplice e non ho trovato quella che mi piaceva qui, quindi ho modificato una libreria per fare quello che volevo. Puoi trovare SSZipArchive utile. (Può anche creare file zip a proposito.)

Utilizzo:

NSString *path = @"path_to_your_zip_file";
NSString *destination = @"path_to_the_folder_where_you_want_it_unzipped";
[SSZipArchive unzipFileAtPath:path toDestination:destination];

Questo codice ha funzionato bene per me per gzip:

il database è stato preparato in questo modo:     gzip foo.db

la chiave scorreva su gzread (). L'esempio sopra legge solo i primi byte CHUNK.

#import <zlib.h>
#define CHUNK 16384


  NSLog(@"testing unzip of database");
  start = [NSDate date];
  NSString *zippedDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"foo.db.gz"];
  NSString *unzippedDBPath = [documentsDirectory stringByAppendingPathComponent:@"foo2.db"];
  gzFile file = gzopen([zippedDBPath UTF8String], "rb");
  FILE *dest = fopen([unzippedDBPath UTF8String], "w");
  unsigned char buffer[CHUNK];
  int uncompressedLength;
  while (uncompressedLength = gzread(file, buffer, CHUNK) ) {
    // got data out of our file
    if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength || ferror(dest)) {
      NSLog(@"error writing data");
    }
  }
  fclose(dest);
  gzclose(file);
  NSLog(@"Finished unzipping database");

Per inciso, posso decomprimere 33 MB in 130 MB in 77 secondi o circa 1,7 MB non compressi / secondo.

Questo codice decomprimerà qualsiasi file .zip nella directory del documento dell'app e otterrà il file dalle risorse dell'app.

self.fileManager = [NSFileManager defaultManager];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSLog(@"document directory path:%@",paths);

self.documentDirectory = [paths objectAtIndex:0];

NSString *filePath = [NSString stringWithFormat:@"%@/abc", self.documentDirectory];

NSLog(@"file path is:%@",filePath);

NSString *fileContent = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"data.zip"];


NSData *unzipData = [NSData dataWithContentsOfFile:fileContent];

[self.fileManager createFileAtPath:filePath contents:unzipData attributes:nil];

// here we go, unzipping code

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

if ([zipArchive UnzipOpenFile:filePath])
{
    if ([zipArchive UnzipFileTo:self.documentDirectory overWrite:NO])
    {
        NSLog(@"Archive unzip success");
        [self.fileManager removeItemAtPath:filePath error:NULL];
    }
    else
    {
        NSLog(@"Failure to unzip archive");
    }
}
else
{
    NSLog(@"Failure to open archive");
}
[zipArchive release];

È davvero difficile decomprimere qualsiasi file zip arbitrario. È un formato di file complesso e ci sono potenzialmente molte diverse routine di compressione che potrebbero essere state utilizzate internamente al file. Info-ZIP ha del codice liberamente autorizzato per farlo ( http: // www .info-zip.org / UnZip.html ) che può essere fatto funzionare su iPhone con qualche hacking, ma l'API è francamente orribile - implica passare argomenti da riga di comando a un falso "principale" che simula il funzionamento di UnZIP (per essere onesti, perché il loro codice non è mai stato progettato per essere utilizzato in questo modo in primo luogo, la funzionalità della libreria è stata montata successivamente).

Se hai il controllo della provenienza dei file che stai provando a decomprimere, vivamente ti consiglio di usare un altro sistema di compressione invece di ZIP. La sua flessibilità e ubiquità lo rendono ideale per il passaggio di archivi di file in persona, ma è molto complicato automatizzare.

zlib non è pensato per aprire i file .zip, ma sei fortunato: la directory contrib di zlib include minizip, che è in grado di usare zlib per aprire i file .zip.

Potrebbe non essere incluso in bundle nell'SDK, ma probabilmente è possibile utilizzare la versione in bundle di zlib. Prendi una copia della fonte zlib e guarda in contrib / minizip.

Non ho usato l'iPhone, ma potresti voler guardare GZIP , che è un libreria zip open source molto portatile disponibile per molte piattaforme.

Ho avuto un po 'di fortuna test questo sul simulatore di iPhone:

NSArray *paths = 
   NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

NSString *saveLocation = 
   [documentsDirectory stringByAppendingString:@"myfile.zip"];

NSFileManager* fileManager = [NSFileManager defaultManager];

if ([fileManager fileExistsAtPath:saveLocation]) {
    [fileManager removeItemAtPath:saveLocation error:nil];

}

NSURLRequest *theRequest = 
             [NSURLRequest requestWithURL:
                [NSURL URLWithString:@"http://example.com/myfile.zip"]
             cachePolicy:NSURLRequestUseProtocolCachePolicy
             timeoutInterval:60.0];    

NSData *received = 
             [NSURLConnection sendSynchronousRequest:theRequest 
                              returningResponse:nil error:nil];    

if ([received writeToFile:saveLocation atomically:TRUE]) {      
    NSString *cmd = 
       [NSString stringWithFormat:@"unzip \"%@\" -d\"%@\"", 
       saveLocation, documentsDirectory];       

    // Here comes the magic...
    system([cmd UTF8String]);       
}

Sembra più facile che scherzare con zlib ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top