Вопрос

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

Решение

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

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

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

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

Другие советы

Я хотел найти простое решение и не нашел здесь того, которое мне понравилось, поэтому я изменил библиотеку, чтобы делать то, что я хотел.Вы можете найти 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];

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

база данных была подготовлена следующим образом:gzip foo.db

ключ зацикливался на gzread().Приведенный выше пример считывает только первые байты блока.

#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 МБ в несжатом виде в секунду.

Этот код разархивирует любой файл .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];

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top