jamirez
jamirez

Reputation: 13

decompressing with zlib in Java (incorrect header check)

I try to program (and understand) compression/decompression. I have a file which is compressed with zlib and I thought that I found the solution to decompress my file:

import java.util.Scanner;
import java.util.zip.*;
import java.io.*;

public class ZLibCompression
{
    public static void main(String args[])throws IOException, DataFormatException {
        File compressed = new File("./MyFile.hlb");
        
        decompress(compressed, new File("./MyFile.txt"));
        
    }
    
    public static void decompress(File compressed, File raw)
            throws IOException
    {
        try (InputStream inputStream = new InflaterInputStream(new FileInputStream(compressed));
             OutputStream outputStream = new FileOutputStream(raw))
        {
            copy(inputStream, outputStream);
        }
    }

 private static void copy(InputStream inputStream, OutputStream outputStream)
            throws IOException
    {
        byte[] buffer = new byte[1000];
        int length;

        while ((length = inputStream.read(buffer)) > 0)
        {
            outputStream.write(buffer, 0, length);
        }
    }
}

But I get the following error stack trace:

Exception in thread "main" java.util.zip.ZipException: incorrect header check
    at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
    at java.base/java.io.FilterInputStream.read(FilterInputStream.java:106)
    at ZLibCompression.copy(ZLibCompression.java:46)
    at ZLibCompression.decompress(ZLibCompression.java:20)
    at ZLibCompression.main(ZLibCompression.java:11)

Then I checked the header of my file and it says:

{
 "compression" : {
  "crc32" : 2575274738,
  "decompressed_size" : 9020404,
  "type" : "zlib"
 },
 "encoded_data" : "eNrsvV2Xm0i

What is my error? I found a Python script that works fine with the same file:

#!/usr/bin/env python
import sys
import os
import json
import base64
import zlib

SETLIST_OR_BUNDLE = "MyFile.hlb"

infile = open(SETLIST_OR_BUNDLE)
data = json.load(infile)
infile.close()

keys = list(data.keys())
if 'encoded_data' in keys:
    unz = zlib.decompress(base64.b64decode(data['encoded_data']))
    setlist_or_bundle = json.loads(unz)
    keys = list(setlist_or_bundle.keys())
    if 'setlists' in keys:
        setlists = setlist_or_bundle['setlists']
    elif 'presets' in keys:
        setlists = [setlist_or_bundle]
    for setlist in setlists:
        keys = list(setlist.keys())
        if 'meta' in keys:
            print()
            print("SETLIST: %s" % (setlist['meta']['name']))
        presets = setlist['presets']
        #print json.dumps(presets, indent=4)
        for preset in presets:
            if 'meta' in list(preset.keys()):
                meta = preset['meta']
                preset_name = meta['name']
                print("  ", preset_name)

I think it has something to do with the base64 part and I found a similar question where someone mentioned "you have to decode the Base64 string into a byte array first" - OK fine - Can anyone explain or give me a link to a tutorial? All I need is the same functionality in Java like the Python script above has - And of course I want to learn something...

Upvotes: 1

Views: 1419

Answers (1)

MonsterDruide1
MonsterDruide1

Reputation: 407

First of all, it looks like your file is not compressed as a whole. Instead, it is a JSON-String containing the actual compressed data as encoded_data. You also need to unwrap the JSON-String then. The easiest way to deal with JSON encrypted data is by using a library. Check this post for some comparisons of different libraries.

Next, as you can see in your python code, the encoded data gets decoded from Base64 before passed through the ZLIB-Decompressor (zlib.decompress(base64.b64decode(data)))

The java equivalent to un-Base64 a String would be:

Base64.getDecoder().decode(string);

Upvotes: 2

Related Questions