Question

I'm working on an iOS app that needs to download ~50 MB of data from time to time. bzip2 gives me the best compression rate (reduces the size to 8 MB).

The problem is: how to decompress the data in the app?

I've done some research - the only two things I found was Keka (but the full source is not public) and C++ source of bzip2 command line tool, which is much too long and too complicated for me to make the necessary adjustments for my app in the time I'm given.

I am looking for something like http://commons.apache.org/proper/commons-compress/ which is used by Android version of the app.

If you know how to do it with 7zip instead of bzip2, that will do - it was just a bit less effective.

Was it helpful?

Solution

bzip2 source code builds to a libbzip2 that you can link to in your code as long as you have a sufficiently good compiler (and I believe that is the case for iOS - although I haven't tried...)

The code you need to write would look something like this:

int error;
const int MAXSIZE = 4096;    // Or some other decent size.
char buffer[MAXSIZE];
FILE *f = fopen("somefile.bz2", "rb"); 
BZFILE* b = BZ2_bzReadOpen(&error, f, 0, 0, NULL, 0);
do {
   BZ2_bzRead(&error, b, buffer, MAXSIZE);
} while(error != BZ_OK);
BZ2_bzReadClose(&error, b);

You may need to add a few more checks for "error", but the concept should work [I think - I just typed all that code in based in the docs and my experience from using this and similar packages in the past].

OTHER TIPS

I suggest you statically link against libbz2. Find the sources in Google.

Mats Petersson's answer points in right direction, but it is not complete.

This code is working on practice:

#import "bzlib.h"

FILE * f = fopen (sourceURL.path.UTF8String, "rb");

int error;
const int MAXSIZE = 4096;
char processedBuffer [MAXSIZE];
char unprocessedBuffer [MAXSIZE];
int unprocessedCount = 0;

do
{
    BZFILE * b = BZ2_bzReadOpen (& error, f, 0, 0, unprocessedBuffer, unprocessedCount);
    while (error == BZ_OK)
    {
        int processedCount = BZ2_bzRead (& error, b, processedBuffer, MAXSIZE);
        
        // here you do what you need with uncompressed data
        for (int i = 0; i < processedCount; i ++)
            printf ("%c", processedBuffer [i]);
    }
    
    void * tmpBuf;
    BZ2_bzReadGetUnused (& error, b, & tmpBuf, & unprocessedCount);
    for (int i = 0; i < unprocessedCount; i ++)
        unprocessedBuffer [i] = ((char *) tmpBuf) [i];
    
    BZ2_bzReadClose (& error, b);
}
while (unprocessedCount > 0 || feof (f) == NO);

fclose (f);

As I include bzip2 as a source code, these files are needed to be added to the project:

blocksort.c
bzlib_private.h
compress.c
crctable.c
decompress.c
huffman.c
randtable.c
bzlib.h
bzlib.c
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top