Разархивируйте код iPhone - PullRequest
26 голосов
/ 05 января 2009

Действительно застрял при попытке написать код для распаковки файла или каталога на iPhone.

Ниже приведен пример кода, который я использую, чтобы разархивировать простой текстовый файл.

Распаковывает файл, но он поврежден.

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

Ответы [ 8 ]

42 голосов
/ 22 июля 2010

Я хотел простое решение и не нашел здесь того, которое мне понравилось, поэтому я изменил библиотеку, чтобы сделать то, что хотел. SSZipArchive может оказаться полезным. (Кстати, он также может создавать zip-файлы.)

Использование:

NSString *path = @"path_to_your_zip_file";
NSString *destination = @"path_to_the_folder_where_you_want_it_unzipped";
[SSZipArchive unzipFileAtPath:path toDestination:destination];
13 голосов
/ 05 января 2009

Действительно ли "sample.zip" был создан с помощью gZip? Расширение .zip обычно используется для архивов, созданных WinZip. Они также могут быть распакованы с использованием zLib, но вам придется анализировать заголовок и использовать другие подпрограммы.

Для проверки взгляните на первые два байта файла. Если это «PK», это WinZip, если это 0x1F8B, это gZip.

Поскольку это специфично для iPhone, посмотрите на это обсуждение форума iPhone SDK , где упоминается miniZip Кажется, что это может обрабатывать файлы WinZip.

Но если это действительно файл WinZip, вы должны взглянуть на спецификацию WinZip и попытаться проанализировать файл самостоятельно. В основном это должен быть синтаксический анализ некоторых значений заголовка, поиск позиции сжатого потока и использование подпрограмм zLib для его распаковки.

12 голосов
/ 16 августа 2009

Этот код хорошо работал для меня gzip:

база данных была подготовлена ​​так: gzip foo.db

ключ зацикливался на gzread (). В приведенном выше примере считываются только первые байты 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");

Кстати, я могу разархивировать 33 МБ в 130 МБ за 77 секунд или около 1,7 МБ без сжатия в секунду.

4 голосов
/ 20 мая 2011

Этот код разархивирует любой файл .zip в каталог документов вашего приложения и получит файл из ресурсов приложения.

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];
1 голос
/ 05 января 2009

zlib не предназначен для открытия файлов .zip, но вам повезло: в каталоге contrib zlib есть мини-архив, который может использовать zlib для открытия файлов .zip.

Возможно, он не входит в комплект SDK, но вы можете использовать его в комплекте с версией zlib. Возьмите копию исходного кода zlib и посмотрите в contrib / minizip.

1 голос
/ 05 января 2009

Очень сложно распаковать любой произвольный zip-файл. Это сложный формат файла, и потенциально существует много различных процедур сжатия, которые могли бы быть использованы внутри файла. Info-ZIP имеет некоторый свободно лицензируемый код для этого (http://www.info -zip.org / UnZip.html ), который можно заставить работать на iPhone с некоторыми взломами, но API откровенно ужасен - он включает в себя передачу аргументов командной строки в фальшивый «main», который имитирует работу UnZIP (честно говоря, это потому, что их код никогда не был спроектирован таким образом, чтобы использовать его в первую очередь, функциональность библиотеки впоследствии была закреплена).

Если у вас есть контроль над тем, откуда приходят файлы, которые вы хотите распаковать, я настоятельно рекомендую использовать другую систему сжатия вместо ZIP. Его гибкость и повсеместность делают его идеальным для передачи архивов файлов от человека к человеку, но автоматизировать его очень неудобно.

0 голосов
/ 12 ноября 2009

Мне повезло, тестируя это на симуляторе 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]);       
}

Это выглядит проще, чем возиться с zlib ...

0 голосов
/ 05 января 2009

Я не пользовался iPhone, но вы можете взглянуть на GZIP , который представляет собой очень портативную zip-библиотеку с открытым исходным кодом, доступную для многих платформ.

...