Код для распаковки iPhone
-
03-07-2019 - |
Вопрос
Действительно зациклился на попытке написать код для распаковки файла или каталога на 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 ...