2

On server (C++), binary data is compressed using ZLib function:

compress2()

and it's sent over to client (Java). On client side (Java), data should be decompressed using the following code snippet:

public static String unpack(byte[] packedBuffer) {
    InflaterInputStream inStream = new InflaterInputStream(new ByteArrayInputStream( packedBuffer);
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    int readByte;
    try {
        while((readByte = inStream.read()) != -1) {
            outStream.write(readByte);
        }
    } catch(Exception e) {
        JMDCLog.logError(" unpacking buffer of size: " + packedBuffer.length);
        e.printStackTrace();
    // ... the rest of the code follows
}

Problem is that when it tries to read in while loop it always throws:

java.util.zip.ZipException: invalid stored block lengths

Before I check for other possible causes can someone please tell me can I compress on one side with compress2 and decompress it on the other side using above code, so I can eliminate this as a problem? Also if someone has a possible clue about what might be wrong here (I know I didn't provide too much of of the code in here but projects are rather big.

Thanks.

subodh
  • 6,136
  • 12
  • 51
  • 73
passenger
  • 23
  • 1
  • 4
  • Just found this, might be helfful: http://www.jcraft.com/jzlib/ – Markus Kreth Mar 26 '13 at 09:08
  • Have you validated that you're getting the correct data out at the client side? Is your `packedBuffer` the right size, for example? – Jon Skeet Mar 26 '13 at 09:18
  • @Jon Skeet Slightly as that is the legacy code of one big system and for start I just wanted to know if I can unpack something compressed with zlib using compress2, with the java code I posted above, so I can move on with investigation of where is the problem. – passenger Mar 26 '13 at 10:48
  • @passenger: But my point is that you shouldn't be trying to diagnose this just from one side. You should look at the results of `compress2()`, checking the length and the data itself against what you receive in the Java code. If you're receiving the wrong data, you've got no hope of receiving it properly. – Jon Skeet Mar 26 '13 at 10:48
  • @Jon Skeet Thanks for your effort. Yes, I do know that, and that's my next step, but as this is the most easily checked and I didn't have so much experience with this in Java, I just wanted to check first if _correctly_ compressed block with compress2 on one side can be decompressed with Java function pasted above? – passenger Mar 26 '13 at 10:55
  • @JonSkeet Checked, packedBuffer is the of correct size. – passenger Mar 26 '13 at 11:08

2 Answers2

0

I think the problem is not with unpack method but in packedBuffer content. Unpack works fine

public static byte[] pack(String s) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DeflaterOutputStream dout = new DeflaterOutputStream(out);
    dout.write(s.getBytes());
    dout.close();
    return out.toByteArray();
}

public static void main(String[] args) throws Exception {
    byte[] a = pack("123");
    String s = unpack(a);   // calls your unpack
    System.out.println(s);
}

output

123
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • 1
    Please don't recommend using the platform default encoding like this - it's highly non-portable. When converting from a String to a byte array or vice versa, you should *always* specify the encoding. – Jon Skeet Mar 26 '13 at 10:49
  • Thanks for responding, but does it also mean, that what is compressed in some C++ code with ZLib (using compress2 function) should be able to be decompressed with my Java unpack function? – passenger Mar 26 '13 at 10:50
  • java.util.zip is based on ZLIB compression library (native dll) and I think that it is compatible with C++ Zlib. But if you can decompress packedBuffer with C++ then it is compressed in a different format. But I am sure there is a C++ - Java compatible format – Evgeniy Dorofeev Mar 26 '13 at 11:37
0
public static String unpack(byte[] packedBuffer) {
    try (GZipInputStream inStream = new GZipInputStream(
                new ByteArrayInputStream(packedBuffer));
            ByteArrayOutputStream outStream = new ByteArrayOutputStream()) {
        inStream.transferTo(outStream);
        //...
        return outStream.toString(StandardCharsets.UTF_8);
    } catch(Exception e) {
        JMDCLog.logError(" unpacking buffer of size: " + packedBuffer.length);
        e.printStackTrace();
        throw new IllegalArgumentException(e);
    }
}

ZLib is the zip format, hence a GZipInputStream is fine. A you seem to expect the bytes to represent text, hence be in some encoding, add that encoding, Charset, to the conversion to String (which always holds Unicode). Note, UTF-8 is the encoding of the bytes. In your case it might be an other encoding.

The ugly try-with-resources syntax closes the streams even on exception or here the return.

I rethrowed a RuntimeException as it seems dangerous to do something with no result.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • What? The zlib format is _not_ the zip format, and the gzip format is _not_ the zlib format. Those are three different things. – Mark Adler Oct 05 '22 at 18:09
  • @MarkAdler [zlib](https://en.wikipedia.org/wiki/Zlib) is definitely more, but if DEFLATE/INFLATE fails, this would seem worth a try. But you seem mere experienced w.r.t. to the zlib aspects and especially compress2. I will wait a bit. – Joop Eggen Oct 05 '22 at 18:58
  • The zlib _library_ is more. The zlib _format_ is a specific thing. – Mark Adler Oct 05 '22 at 19:42