CompressString TypeLoadException and NotSupportedException under CF2

Oct 28, 2009 at 1:59 PM

Hi,

I want to continue an old discussion, about compressing strings.

http://dotnetzip.codeplex.com/Thread/View.aspx?ThreadId=65854

My problem is when I call GZipStream.CompressString under CF2 and WM6, I get TypeLoadException.

GZipStream.CompressString(s1)
e.Message=TypeLoadException

stack trace=
at cfzipTest.Form1.CompressTest()
at cfzipTest.Form1.button1_Click()
at System.Windows.Forms.Control.OnClick()
at System.Windows.Forms.Button.OnClick()
at System.Windows.Forms.ButtonBase.WnProc()
at System.Windows.Forms.Control._InternalWnProc()
at Microsoft.AGL.Forms.EVL.EnterMainLoop()
at System.Windows.Forms.Application.Run()
at cfzipTest.Program.Main()

I try to replace  the call to ZlibStream.CompressString, and got NotSupportedException.

ZlibStream.CompressString(s1)
e.Message=NotSupportedException

stack trace=
at System.RuntimeType.InvokeMember()
at System.Type.InvokeMember()
at Ionic.Zlib.ZlibBaseStream.CompressString()
at Ionic.Zlib.ZlibStream.CompressString()
at cfzipTest.Form1.CompressTest()
at cfzipTest.Form1.button4_Click()
at System.Windows.Forms.Control.OnClick()
at System.Windows.Forms.Button.OnClick()
at System.Windows.Forms.ButtonBase.WnProc()
at System.Windows.Forms.Control._InternalWnProc()
at Microsoft.AGL.Forms.EVL.EnterMainLoop()
at System.Windows.Forms.Application.Run()
at cfzipTest.Program.Main()

the same exception i got with calling DeflateStream.CompressString.

 

At one of the discussions you wrote that the WM5 does not contains the requeired iso-8859-1 code page. so I try to call that function at CE5 mobile with CF2, and everyone of the calls got the NotSupportedException exception.

with the stack trace=
at System.RuntimeType.InvokeMember()
at System.Type.InvokeMember()
at Ionic.Zlib.ZlibBaseStream.CompressString()
at Ionic.Zlib.ZlibStream.CompressString()
at cfzipTest.Form1.CompressTest()
at cfzipTest.Form1.button4_Click()
at System.Windows.Forms.Control.OnClick()
at System.Windows.Forms.Button.OnClick()
at System.Windows.Forms.ButtonBase.WnProc()
at System.Windows.Forms.Control._InternalWnProc()
at Microsoft.AGL.Forms.EVL.EnterMainLoop()
at System.Windows.Forms.Application.Run()
at cfzipTest.Program.Main()

I use the latest version of the v1.8 kit. v1.8.4.26

 

What did i miss?

 

sorry for the long time from my latest response ...

 

Coordinator
Oct 28, 2009 at 7:02 PM

You didn't miss anything.  I missed something.  I used the Type.InvokeMember method, which is not supported on the CompactFramework, and I didn't test it.  

It throws an exception, always. 

The fix is easy.  I'll put it together and upload it.

 

Coordinator
Oct 28, 2009 at 8:03 PM

I just posted an update of v1.8: v1.8.4.27.    It's a very small change so I would suggest that you update right away.  The DeflateStream.CompressString() should work for you now.  Also ZlibStream.CompressString() should work.

GZipStream.CompressString() will still fail because of the iso-8859-1 platform issue.

 

Oct 29, 2009 at 10:23 AM

They both works fine !

for my basic tests, the DeflateStream.CompressString generate smaller byte array than ZlibStream.CompressString(). by a few bytes (for 30K string length). is there any other considerations (than size) i should take for selecting/using one of those methods?

Thanks !

 

Coordinator
Oct 29, 2009 at 12:04 PM

Thanks for testing it. I'm glad it's working for you.

You asked about considerations for choosing ZLIB versus DEFLATE.  The short answer is, in your case, it probably doesn't matter which you choose.   If I were selecting a compression algorithm for general purpose use, I would select ZLIB.

The ZLIB compression uses the same compression algorithm as DEFLATE.  The difference is, ZLIB adds extra "metadata" around the DEFLATE'd data.  If you stripped off that metadata, or data about the data, then you would be left with the identical DEFLATE stream.   The purpose of the ZLIB metadata is to provide extra services or capabilities.  If you care, you can read IETF RFC 1950 to learn specifically what ZLIB adds.  There are a bunch of options that are not actually used in practice. For example, the compression method.  In theory ZLIB can be used with one of a number of compression methods.  In practice, ZLIB always uses DEFLATE.  As a result, much of the ZLIB metadata is of no practical value. 

There's one possibly interesting piece of ZLIB metadata: the Adler32 checksum.  This provides a data integrity check that you do not get with DEFLATE alone. A DEFLATE stream is fairly fragile - if you change one byte of the compressed data, your decompression is likely to fail in an obvious manner.  But it's theoretically possible to have corruption in the deflate'd stream of data, that results in a valid deflate stream.  When you decompress the corrupted data, you get a valid output - no errors during decompression - though because of the upstream corruption, the resulting decompressed text does not match the original.  

To avoid this problem, ZLIB has a checksum that will detect corruption, even if the compressed stream decompresses without error. A compliant ZLIB processor (such as is included in DotNetZip) must throw an error if the checksum does not match.

It's going to be a rare case, though.  In most cases if there is corruption in the compressed data, it will not decompress properly - you'll get an error even without the checksum verification.  On the other hand, because ZLIB implies such a small amount of overhead, in the general case, it's worth it to have the extra protection.  Finally, in specific applications, you may not need or not want the ZLIB checksum. For example, in a .zip file, DEFLATE is just fine because there is a separate, zip-specific checksum on each DEFLATE stream.

Probably more information than you wanted.  Sometimes I can't help mesef.

 

Nov 2, 2009 at 9:22 AM

Hi again,

I don't know if it supose to be like that, but when i'm using DeflateStream.CompressString on small strings (mine is an empty XML, "<ALL></ALL>"), the DeflateStream.UncompressString return empty string. No exception.

The ZlibStream.CompressString and ZlibStream.UncompressString works fine.

Is it part of the fragility of the DeflateStream?

 

Coordinator
Nov 2, 2009 at 9:38 AM

No, it should not do that.  Sounds like a problem to me.

Coordinator
Nov 2, 2009 at 9:40 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Nov 4, 2009 at 8:34 AM

I tried testing this, could not reproduce the problem you reported.  It should be a very simple test case, I would think.  Do you have source code that reliably demonstrates the problem?

  string s1 = "<ALL></ALL>";
  byte[] b = Ionic.Zlib.DeflateStream.CompressString(s1);
  string s2 = Ionic.Zlib.DeflateStream.UncompressString(b);
  // at this point s1 and s2 are equal.