Codice di decompressione iPhone
-
03-07-2019 - |
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);
}
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 ...