iPhone разархивировать код

Действительно застрял при попытке написать код для распаковки файла или каталога на 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);  
}

person TonyNeallon    schedule 05.01.2009    source источник


Ответы (8)


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

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

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

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

person schnaader    schedule 05.01.2009
comment
У меня есть вопрос ... будет ли использование miniZip частным, недокументированным или непубличным API? Пожалуйста помоги. - person Pria; 28.09.2010
comment
Это нормально - вы можете использовать библиотеки, которые вы сами связываете с приложением. Проблема с частным / недокументированным API обычно связана с кодом Apple. - person Jay Peyer; 16.03.2011

Мне нужно было простое решение, и я не нашел здесь того, что мне понравилось бы, поэтому я изменил библиотеку, чтобы делать то, что хотел. Вы можете найти 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];
person Sam Soffes    schedule 21.07.2010
comment
Так это для файлов gzip или winzip? - person whitneyland; 15.11.2011
comment
Это лучшее решение, которое я когда-либо видел, отличная работа! - person T. Markle; 04.03.2012

Этот код хорошо работал у меня с 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 МБ без сжатия в секунду.

person Carl Coryell-Martin    schedule 16.08.2009
comment
Именно то, что мне нужно. Спасибо! - person Jens Willy Johannsen; 24.03.2011
comment
Я успешно использовал gzip на iOS, но в моем последнем проекте мне нужно извлечь несколько файлов, поэтому сейчас я исследую SSZipArchive. - person neoneye; 05.05.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];
person marshad13    schedule 20.05.2011
comment
@ marshad13 Откуда взялся класс ZipArchive? Я просмотрел документацию по ios и osx, но мне не удалось найти класс - person Anthony Kong; 26.05.2013

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

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

person th_in_gs    schedule 05.01.2009
comment
Я не согласен, что это так сложно. В большинстве случаев у вас будет стандартный ZIP-файл с использованием deflate. В этом случае вам нужно только найти правильную позицию и использовать zLib deflate, который будет похож на опубликованный код, только немного длиннее и с использованием других подпрограмм. - person schnaader; 05.01.2009
comment
Это не сложно, только если вы делаете предположения, и многие старые ZIP-файлы в дикой природе не используют deflate. Если вы можете гарантировать, что все файлы, которые вы будете использовать, относятся к «типу» ZIP, ничего страшного. Если вы контролируете сжатие, зачем использовать ZIP, если файлы также не предназначены для пользователя? - person th_in_gs; 06.01.2009

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

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

person Jeff M    schedule 05.01.2009

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

person SmacL    schedule 05.01.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 ...

person James Boston    schedule 12.11.2009
comment
Работает, но, к сожалению, не НА устройстве - person scud; 16.02.2010
comment
system () ... надеюсь это шутка - person Mike Weller; 14.06.2010
comment
Я считаю, что это очень хорошее решение, это не шутка. Я сейчас протестирую это решение. - person user1462586; 18.12.2019
comment
он говорит, что система недоступна на iOS. - person user1462586; 18.12.2019