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を使用して解凍することもできますが、ヘッダーを解析して他のルーチンを使用する必要があります。
確認するには、ファイルの最初の2バイトを見てください。 「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()をループしていました。上記の例では、最初の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");
ちなみに、私は77MBで33MBを130MBに解凍できます。
このコードは、.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は率直に言って恐ろしいです-それはシミュレートする偽の「メイン」にコマンドライン引数を渡すことを含みますUnZIPの実行(公平を期すため、そもそもコードがこのように使用されるように設計されていなかったため、その後ライブラリ機能が追加されました)。
解凍しようとしているファイルがどこから来ているかを制御できる場合、ZIPの代わりに別の圧縮システムを使用することを非常にお勧めします。柔軟性と遍在性により、ファイルのアーカイブを個人間でやり取りするのに最適ですが、自動化するのは非常に厄介です。
zlibは.zipファイルを開くためのものではありませんが、幸運です。zlibのcontribディレクトリにはminizipが含まれており、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をいじるよりも簡単に見える...