Data compression in C#/J# and Java

Environment:
Windows, Java 1.4, .NET Framework 1.1

Hi,

I'm distributing dynamic content (always strings) by a .NET web page, and consume it by a Java client.  I'd like to compress this content to speed up the time to delivery.

Referencing the J# library in the .NET project, I can utilize the Microsoft java.util.zip package.  In my case, I'm - both client- and server-side - using the Java Inflater resp. Deflater objects.  The Java resp. C# code is almost similar, and compression / decompression works fine for each platform.

I've made sure the strings which ought to be decompressed at the client exactly matches the strings compressed at the server (as aforementioned, decompressing them at the server does work).


PROBLEM:

In general and partly, the Java client is able to decompress the string compressed by the C# server.
But, the longer the string gets, the worse is the decompression success rate.  I.e., the first 20 characters are decompressed 100% correct.  20% of the next 20 characters are not - or wrongly - decompressed, 30% of the next 20 characters, and so on.


I'd appreciate any well-directed hints.
Thanks indeed.


---
Additional information:
1. I'm aware there is GZIPInputStream, etc.  I'm not using it as I ran into problems with converting Java byte arrays to strings.  In C# web applications, I can output strings or byte[], but not sbyte[] (which is the equivalent of the Java byte[] type.

2. Also, the GZIPOutputStream complained it would need a dictionary (setDictionary()).  I guess that's near where the solution is.

3. I'm also aware IIS 6.0 can be set up to deliver gzip'ed, dynamic content.  I didn't want to choose this way as, AFAIK, any IIS website on this server would be concerned.

Thanks again.
LVL 15
robbertAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

lcwidingCommented:
How are you passing the compressed data from the server to the client? I have used both libraries to decompress/compress data with on problems. If you are streaming the data, and processing it as it streams down, you may be hitting timeout conditions, and not handling those correctly.

Some example code from both sides might help figure out the issue as well.
0
robbertAuthor Commented:
I'm using Response.Write(), after setting the content-encoding to UTF-8.

I'm stepping through the server-side and client-side code at run-time, using the Visual Studio .NET and Eclipse debugger:  The string at the client is literally the same as the one sent from the server.  Additionally, my test projects are kept simple, in order to eliminate additional possible error sources.

Remember:  The first portions of the string get decompressed fine.  There is no fixed position at which decompression fails, generally.  The problem is, the longer the string gets, the more failures occur decompressing single characters.  Even at the end of the string, some random characters may get "translated" correctly.

Thanks.
0
sciuriwareCommented:
Rest assured that GZIPInputStream and GZIPOutputStream are safe (upto 4 Gb!!!!).
The problem is certainly not in there, I did a lot compression and expanding,
so much that I found the 4Gb barrier.
;JOOP!
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

robbertAuthor Commented:
I guess the problem is the string encoding.

HttpURLConnection.getContentEncoding() returns "text/plain; charset=utf-8".
I have to convert the string received to a byte array. I was using:

          byte[] bytes = new byte[str.length()]; // length is 35
        for (int i = 0; i < str.length(); i++)
        {
            char c = str.charAt(i);
            int charCode = c;
            bytes[i] = (byte)charCode;
        }

That way, ASCII characters get decoded fine but, i.e., Umlauts (äöü) get decoded as &#65508;&#65526;&#65532;.

I also tried java.nio(.charset),

          Charset charset = Charset.forName("UTF-8");
          ByteBuffer byteBuffer = charset.encode(str);
          byte[] bytes = byteBuffer.array();  // length is 76

but that resulted in the error java.util.zip.DataFormatException: invalid distance code
0
robbertAuthor Commented:
BTW, String.getBytes() and getBytes(charsetName) resulted in other DataFormatExceptions.
0
lcwidingCommented:
From what you have said here, it sonuds like you are taking the output from the compressor, and writing that out as a string to be read by the client application. Without some form of encoding (and standard HTTP encoding will not work), this will fail.

The easiest encoding would be to to convert each byte into two hexidecimal characters, write that stream out, and convert them back to bytes in the Java client (using Integer.parseInt(s,16)).

To provide a better conversion process, you can look at Base64 encoding. Here is a link to some Java code to support this: http://mindprod.com/products.html#BASE64

There may be easier ways to implement this, perhaps direct through a MIME type, but I have not worked with those much myself.

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
robbertAuthor Commented:
> it sonuds like you are taking the output from the compressor, and writing that out as a string to be read by the client application. Without some form of encoding (and standard HTTP encoding will not work), this will fail.

That's what I'm doing, and, in the meantime, it started working!
As for the record, at the server, the data is compressed like in this sample: http://msdn.microsoft.com/msdnmag/issues/03/06/ZipCompression/default.aspx

At the client side, I firstly read in the bytes returned by the HttpURLConnection. Then:
String x = new String(bytes, "UTF-8");  // that's all
Then, decompress the string by Java code being quite identical to the code in the aforementioned link.

> look at Base64 encoding

Sorry that I'm contradicting.  I've tried that.  Base64 encoding will blow up the input strings.  Even compressed, this results in larger strings than the initial ones.

- Thank you for your support, though.  Getting input is very valuable to me.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.