Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ZLib in iPhone unable to decompress data

I am trying to decompress data using the ZLib in iPhone, but it always through error of "Invalid header Check".

To compress the data I am using the following in Java

Implementation: Standard Java implementation for Zlib

Deflator : java.util.zip.Deflater

version 1.45, 04/07/06

Compression level: BEST_COMPRESSION

In iPhone the following is the code for decompressing:

- (NSData *)zlibInflate
{
if ([self length] == 0) return self;

unsigned full_length = [self length];
unsigned half_length = [self length] / 2;

NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
BOOL done = NO;
int status;

z_stream strm;
strm.next_in = (Bytef *)[self bytes];
strm.avail_in = [self length];
strm.total_out = 0;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;

if (inflateInit (&strm) != Z_OK) return nil;

while (!done)
{
    // Make sure we have enough room and reset the lengths.
    if (strm.total_out >= [decompressed length])
        [decompressed increaseLengthBy: half_length];
    strm.next_out = [decompressed mutableBytes] + strm.total_out;
    strm.avail_out = [decompressed length] - strm.total_out;

    // Inflate another chunk.
    status = inflate (&strm, Z_SYNC_FLUSH);
    if (status == Z_STREAM_END) done = YES;
    else if (status != Z_OK) {
        NSLog(@"%s", strm.msg);
        break;
    }
}
if (inflateEnd (&strm) != Z_OK) return nil;

// Set real length.
if (done)
{
    [decompressed setLength: strm.total_out];
    return [NSData dataWithData: decompressed];
}
else return nil;
}

Following is a sample compressed string:

xÚÝUko²Jþ~?­ó?¥¾?¤?©?´ÚjCMX,Òµ?ª?µßVX¹È­?¿.øë_?¯¶ZÏ%íùxHH&Ã<ÏÌ3ÌÎ
@2.ðE?ºqþpéEzÏ09IoÒ?ª? ?®?£àÌönì$brÛ#fl95?¿»a//Tçáò?¢?¿½
µ©ÊÃÉPÔ¼:8y¦ý.äÎ?µ?¥?¼y?©ã¯9ö?¥½?¢±ÝûwÛ?§ãga?©á8?¨?­m\Õ?»6,'Îe?¬}(L}7ÆÅ6#gJ(¥7´s?¬d.ó,Ë°¦prßýÕÖ? 

Below is the function for compresser:

public static byte[] compress(String s) {
       Deflater comp = new Deflater();
       //comp.setLevel(Deflater.BEST_COMPRESSION);

       comp.setInput(s.getBytes());

       comp.finish();
       ByteArrayOutputStream bos = new ByteArrayOutputStream(s.length());

       // Compress the data
       byte[] buf = new byte[1024];
       try {
            while (!comp.finished()) {
                  int count = comp.deflate(buf);
                  bos.write(buf, 0, count);
            }
            bos.close();
       } catch (Exception e) {
            //Log.d(TAG, e.getMessage());
            e.printStackTrace();
       }

       // Get the compressed data
       byte[] compressedData = bos.toByteArray();

       // put in this fix for Symbol scanners
       byte[] compressedDataForSymbol = mungeForSymbol(compressedData);
       /*
       * byte[] decompressedDataForSymbol =
       * decompressedDataAfterSymbol(compressedDataForSymbol); // check they
       * are the same for(int i=0;i<compressedData.length;i++) { if
       * (compressedData[i] != decompressedDataForSymbol[i]) {
       * //System.out.println("Error at " + i); } }
       */
       return compressedDataForSymbol;
       // return s.getBytes();

 }
like image 280
user2020313 Avatar asked Jan 29 '13 04:01

user2020313


1 Answers

Using Java Deflater with default compression level creates output encoded data with header with first two bytes 0x78 0x9c. These are not used in IOS. Just remove the first two bytes and try the Inflate ie decompression in IOS. It should work. I had faced the same issue, But i wanted data from IOS(compressed) to android(decompressed).

like image 86
virtplay Avatar answered Oct 13 '22 09:10

virtplay