2

Firstly, I'm noticing that compressing the object requires more bytes then purely representing the object in binary form. (228 vs 166).

Secondly, I can't seem to decompress it.

Also, I can't use the nice CopyTo functionality since I don't have version 4 of the .NET framework.

What needs to go in the last DeflateStream using block?

MyClass MyObj = new MyClass();
MyObj.MyProp1 = true;
MyObj.MyProp2 = "Dee";
MyClass MyObAfterSerDeser = null;
using (MemoryStream ms = new MemoryStream())
{
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(ms, MyObj);
    byte[] prebytes = ms.ToArray(); // length 166.
    ms.SetLength(0L); 
    using(MemoryStream tmpms = new MemoryStream())
    {
        using (DeflateStream dsc = new DeflateStream(tmpms, CompressionMode.Compress))
        {
            dsc.Write(prebytes, 0, prebytes.Length);
            tmpms.WriteTo(ms); // unforunately though, just want the # of compressed bytes.
        }
    }
    byte[] cbytes = ms.ToArray();  // length 228.  Longer than uncompressed version!
    ms.SetLength(0L);

    using (MemoryStream tmpms = new MemoryStream())
    {
        tmpms.Write(cbytes, 0, cbytes.Length);
        tmpms.Position = 0;
        using (DeflateStream dsd = new DeflateStream(tmpms, CompressionMode.Decompress))
        {
            byte[] dbytes = new byte[cbytes.Length];
            dsd.Read(dbytes, 0, dbytes.Length);
            int offset = ReadAllBytesFromStream(dsd, dbytes);  // written by Mr. Skeet.
            // dsd.Write(dbytes, 0, cbytes.Length);
            // dsd.Read(dbytes, 0, dbytes.Length);
            ms.Write(dbytes, 0, offset);
        }
    }
    MyObAfterSerDeser = (MyClass)bf.Deserialize(ms);
}
dtb
  • 213,145
  • 36
  • 401
  • 431
user420667
  • 6,552
  • 15
  • 51
  • 83

2 Answers2

3

There is no guarantee that deflate will always result in a smaller size (although it should just use a "stored/raw/undeflated" section in such cases).

The .NET deflate implementation (which is also used in the GZipStream) is known to be particular bad (although conforming) when encoding small and/or already compressed data. There are 3rd party libraries, including DotNetZip, that correct these two issues present in the .NET BCL.

When I do deflate compression (on small pieces of data) I have a "deflated" flag so the stream I store is only sometimes deflated, depending upon if the deflate was "worth it".

Happy coding.

  • Thanks. +1 for addressing problem 1. I sort of figured it might have something to do w/ the smallness of the data being compressed. Unfortunately the decompression step still doesn't work. – user420667 Oct 06 '11 at 21:27
0

You can initialize memorystream with bytes already like this (no need to write & position):

Code inside is what CopyTo does in .NET 4.0

MemoryStream output = new MemoryStream();
try
{
   using (MemoryStream ms = new MemoryStream(cbytes))
   using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress, true)) {

    int num;
    byte[] buffer = new byte[100];
    while ((num = ds.Read(buffer, 0, buffer.Length)) != 0)
    {
        output.Write(buffer, 0, num);
    }
   }
   MyObAfterSerDeser = (MyClass)bf.Deserialize(output);
}
finally
{
    output.Dispose();
}

I got this code for a reason (notice dispose) I believe, I remember it was not working when I was trying to Dispose it by means of using output instead which definately would look cooler.

Valentin Kuzub
  • 11,703
  • 7
  • 56
  • 93
  • I tried this but it complained that output was empty. I noticed it was skipping the while loop, as if ds.Read(...) wasn't doing anything. I tried your code where my old decompression code was, except i had to rename your ms to tmpms. In any case, it still isn't working. Any suggestions? – user420667 Oct 06 '11 at 21:26