Código de Descompresión de iPhone

Realmente trabado al tratar de escribir código para descomprimir un archivo o directorio en el iPhone.

A continuación se muestra un código de muestra que estoy usando para tratar de descomprimir un archivo de texto simple.

Descomprime el archivo pero está dañado.

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

¿Realmente se ha creado “sample.zip” con gZip? La extensión .zip generalmente se usa para archivos creados por WinZip. Esos también se pueden descomprimir usando zLib, pero tendría que analizar el encabezado y usar otras rutinas.

Para verificar, eche un vistazo a los dos primeros bytes del archivo. Si es ‘PK’, es WinZip, si es 0x1F8B, es gZip.

Debido a que este es un iPhone específico, eche un vistazo a esta discusión del foro de iPhone SDK donde se menciona miniZip . Parece que esto puede manejar archivos WinZip.

Pero si realmente es un archivo de WinZip, debería echar un vistazo a la especificación de WinZip e intentar analizar el archivo usted mismo. Básicamente, debería analizar algunos valores de encabezado, buscar la posición del flujo comprimido y usar rutinas zLib para descomprimirlo.

Quería una solución fácil y no encontré una que me gustara aquí, así que modifiqué una biblioteca para hacer lo que quería. Puede encontrar útil SSZipArchive . (Por cierto, también puede crear archivos zip).

Uso:

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

Este código funcionó bien para mí para gzip:

la base de datos se preparó así: gzip foo.db

la clave estaba girando sobre el gzread (). El ejemplo anterior solo lee los primeros bytes CHUNK.

 #import  #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"); 

Por cierto, puedo descomprimir 33 MB en 130 MB en 77 segundos o alrededor de 1,7 MB sin comprimir / segundo.

Este código descomprimirá cualquier archivo .zip en el directorio de documentos de la aplicación y obtendrá el archivo de los recursos de la aplicación.

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

Es realmente difícil descomprimir cualquier archivo zip arbitrario. Es un formato de archivo complejo, y hay potencialmente muchas rutinas de compresión diferentes que podrían haberse utilizado internamente en el archivo. Info-ZIP tiene algún código libremente adjudicable para hacerlo ( http://www.info-zip.org/UnZip.html ) que se puede hacer para que funcione en el iPhone con alguna piratería, pero la API es francamente horrible: implica pasar los argumentos de la línea de comandos a un falso “principal” que simula la ejecución de UnZIP (para ser justos, es porque su código nunca fue diseñado para ser usado así en primer lugar, la funcionalidad de la biblioteca se atorniló después).

Si tiene control sobre el origen de los archivos que está intentando descomprimir, le recomiendo utilizar otro sistema de compresión en lugar de ZIP. Su flexibilidad y ubicuidad lo hacen ideal para pasar archivos de persona a persona, pero es muy difícil de automatizar.

zlib no está destinado a abrir archivos .zip, pero tiene suerte: el directorio contrib de zlib incluye minizip, que puede usar zlib para abrir archivos .zip.

Es posible que no se incluya en el SDK, pero probablemente pueda usar la versión incluida de zlib. Tome una copia de la fuente zlib y mire en contrib / minizip.

No he usado el iPhone, pero es posible que desee ver GZIP , que es una biblioteca zip de código abierto muy portátil disponible para muchas plataformas.

Tuve algo de suerte probando esto en el simulador de 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]); } 

Parece más fácil que juguetear con zlib …