views:

12581

answers:

11
+7  Q: 

iPhone Unzip code

Hi There,

Really stuck on trying to write code to unzip a file or directory on the iPhone.

Below is some sample code that Im using to try and unzip a simple text file.

It unzips the file but its corrupt. Would be really grateful is someone has an example or any pointers.

Thanking you

Tony

(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);  

}

A: 

I haven't used the iPhone, but you may want to look at GZIP, which is a very portable open source zip library available for many platforms.

Shane MacLaughlin
+7  A: 

Has "sample.zip" really been created with gZip? The .zip extension usually is used for archives created by WinZip. Those can also be decompressed using zLib, but you'd have to parse the header and use other routines.

To check, have a look at the first two bytes of the file. If it is 'PK', it's WinZip, if it's 0x1F8B, it's gZip.

Because this is iPhone specific, have a look at this iPhone SDK forum discussion where miniZip is mentioned. It seems this can handle WinZip files.

But if it's really a WinZip file, you should have a look at the WinZip specification and try to parse the file yourself. It basically should be parsing some header values, seeking the compressed stream position and using zLib routines to decompress it.

schnaader
I have a query...whether using miniZip will come under using private API or undocumented API or non-public API? Please help.
Pria
A: 

It's really hard to unzip any arbitrary zip file. It's a complex file format, and there are potentially many different compression routines that could have been used internally to the file. Info-ZIP has some freely licencable code to do it (http://www.info-zip.org/UnZip.html) that can be made to work on the iPhone with some hacking, but the API is frankly horrible - it involves passing command-line arguments to a fake 'main' that simulates the running of UnZIP (to be fair that's because their code was never designed to be used like this in the first place, the library functionality was bolted on afterwards).

If you have any control of where the files you're trying to unzip are coming from, I highly recommend using another compression system instead of ZIP. It's flexibility and ubiquity make it great for passing archives of files around in person-to-person, but it's very awkward to automate.

th_in_gs
I'd not agree that it's that complicated. In most cases, you'll have a standard ZIP file using deflate. In this case, you'll only have to seek to the correct position and can use zLib deflate which would look similar to the posted code, only slightly longer and using different routines.
schnaader
It's only not complex if you make assumptions, and many older ZIP files in the wild don't use deflate. If you can guarantee all the files you'll be using are of the right 'kind' of ZIP, that's okay. If you're controlling the compression though, why use ZIP unless the files are also for the user?
th_in_gs
+1  A: 

zlib isn't meant to open .zip files, but you are in luck: zlib's contrib directory includes minizip, which is able to use zlib to open .zip files.

It may not be bundled in the SDK, but you can probably use the bundled version of zlib use it. Grab a copy of the zlib source and look in contrib/minizip.

Jeff M
+5  A: 

This code worked well for me for gzip:

the database was prepared like this: gzip foo.db

the key was looping over the gzread(). The example above only reads the first CHUNK bytes.

#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");

Incidentally, I can unzip 33MB into 130MB in 77 seconds or about 1.7 MB uncompressed/second.

Carl Coryell-Martin
A: 

I had some luck testing this on the iPhone simulator:

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]);       
}

It looks easier than fiddling about with zlib...

James Boston
Works, but unfortunately not ON the device
hecta
system()... I hope this is a joke
Mike Weller
A: 

Is there any good example(sample code ) or documentation for minizip library.I just linked it abut dont know how to use api exactly,I know header files exaplains apis separately.

sachin
A: 

is any document available for how to unzip zipped file in iphone app?

Abhijeet Barge
+2  A: 

I wanted an easy solution and didn't find one I liked here, so I modified a library to do what I wanted. You may find SSZipArchive useful.

Usage:

NSString *path = @"path_to_your_zip_file";
NSString *destination = @"path_to_the_folder_where_you_want_it_unzipped";
[SSZipArchive unzipFileAtPath:path toDestination:destination];
Sam Soffes
A: 

James Boston's reply worked like magic. Thanks a lot dude.

A: 

are you sure that is not working on iphone?????

ram