Add support for creating zip files

Basic zip files can be created (or appended to) by supplying the
path to a zip file and either paths to existing files or NSData
objects along with filenames.
This commit is contained in:
Johnnie Walker 2011-12-20 09:24:56 +00:00
parent ada9722309
commit 4fa1e0d060
3 changed files with 168 additions and 7 deletions

View File

@ -7,10 +7,25 @@
//
#import <Foundation/Foundation.h>
#import "minizip/zip.h"
@interface SSZipArchive : NSObject
@interface SSZipArchive : NSObject {
@private
NSString *_path;
zipFile _zip;
}
// Unzip
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination;
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error;
// Zip
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)filenames;
- (id)initWithPath:(NSString *)path;
- (BOOL)open;
- (BOOL)writeFile:(NSString *)path;
- (BOOL)writeData:(NSData *)data filename:(NSString *)filename;
- (BOOL)close;
@end

View File

@ -148,6 +148,128 @@
return success;
}
#pragma mark - unzip
#define CHUNK 16384
+ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths {
BOOL success = NO;
SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path];
if ([zipArchive open]) {
for (NSString *path in paths) {
[zipArchive writeFile:path];
}
success = [zipArchive close];
}
[zipArchive release];
return success;
}
- (id)initWithPath:(NSString *)path
{
self = [super init];
if (self) {
_path = [path copy];
// Initialization code here.
}
return self;
}
- (void)dealloc {
[_path release];
[super dealloc];
}
- (BOOL)open {
NSAssert((_zip == NULL), @"Attempting open an archive which is already open");
_zip = zipOpen([_path UTF8String], APPEND_STATUS_CREATE);
return (NULL != _zip);
}
- (BOOL)writeFile:(NSString *)path {
NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened");
FILE *input = fopen([path UTF8String], "r");
if (NULL == input) {
return NO;
}
zipOpenNewFileInZip(_zip,
[[path lastPathComponent] UTF8String],
NULL,
NULL,
0,
NULL,
0,
NULL,
Z_DEFLATED,
Z_DEFAULT_COMPRESSION);
void *buffer = malloc(CHUNK);
unsigned int len = 0;
while (!feof(input)) {
len = (unsigned int) fread(buffer, 1, CHUNK, input);
zipWriteInFileInZip(_zip, buffer, len);
}
zipCloseFileInZip(_zip);
free(buffer);
return YES;
}
- (BOOL)writeData:(NSData *)data filename:(NSString *)filename {
NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened");
NSAssert((data != NULL), @"Nil data");
zipOpenNewFileInZip(_zip,
[filename UTF8String],
NULL,
NULL,
0,
NULL,
0,
NULL,
Z_DEFLATED,
Z_DEFAULT_COMPRESSION);
void *buffer = malloc(CHUNK);
unsigned int offset = 0;
NSUInteger length = [data length];
unsigned int chunk_length;
while (offset < length) {
chunk_length = MIN(CHUNK, ((unsigned int) length)-offset);
[data getBytes:&buffer range:NSMakeRange(offset, chunk_length)];
zipWriteInFileInZip(_zip, buffer, chunk_length);
offset += chunk_length;
}
zipCloseFileInZip(_zip);
free(buffer);
return YES;
}
- (BOOL)close {
NSAssert((_zip != NULL), @"Attempting to close an archive which was never opened");
zipClose(_zip, NULL);
return YES;
}
#pragma mark - Private

View File

@ -11,21 +11,32 @@
@interface SSZipArchiveTests ()
- (NSString *)_cachesPath;
- (NSString *)_createOutputPath;
@end
@implementation SSZipArchiveTests
- (void)testBasicUnzipping {
NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestArchive" ofType:@"zip"];
NSString *outputPath = [[self _cachesPath] stringByAppendingPathComponent:@"basic"];
- (void)testBasicZipping {
NSString *outputPath = [self _createOutputPath];
NSArray *inputPaths = [NSArray arrayWithObjects:
[outputPath stringByAppendingPathComponent:@"Readme.markdown"],
[outputPath stringByAppendingPathComponent:@"LICENSE"],
nil];
NSString *archivePath = [outputPath stringByAppendingPathComponent:@"CreatedArchive.zip"];
[SSZipArchive createZipFileAtPath:archivePath withFilesAtPaths:inputPaths];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:outputPath]) {
[fileManager createDirectoryAtPath:outputPath withIntermediateDirectories:YES attributes:nil error:nil];
}
STAssertTrue([fileManager fileExistsAtPath:archivePath], @"Archive created");
}
- (void)testBasicUnzipping {
NSString *zipPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"TestArchive" ofType:@"zip"];
NSString *outputPath = [self _createOutputPath];
[SSZipArchive unzipFileAtPath:zipPath toDestination:outputPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *testPath = [outputPath stringByAppendingPathComponent:@"Readme.markdown"];
STAssertTrue([fileManager fileExistsAtPath:testPath], @"Readme unzipped");
@ -40,6 +51,19 @@
#pragma mark - Private
- (NSString *)_createOutputPath {
NSString *outputPath = [[self _cachesPath] stringByAppendingPathComponent:@"basic"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:outputPath]) {
[fileManager createDirectoryAtPath:outputPath withIntermediateDirectories:YES attributes:nil error:nil];
}
// NSLog(@"outputPath: %@", outputPath);
return outputPath;
}
- (NSString *)_cachesPath {
return [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
stringByAppendingPathComponent:@"com.samsoffes.ssziparchive.tests"];