Search code examples
c#serializationmemorystreamdeflatebinary-serialization

DeflateStream doesnt work on MemoryStream?


I have the following piece of code:

MemoryStream resultStream = new MemoryStream();
string users = ""//Really long string goes here
BinaryFormatter bFormatter = new BinaryFormatter();
using (MemoryStream assignedUsersStream = new MemoryStream())
{
    bFormatter.Serialize(assignedUsersStream, users);
    assignedUsersStream.Position = 0;

    using (var compressionStream =
        new DeflateStream(resultStream, CompressionLevel.Optimal))
    {
        assignedUsersStream.CopyTo(compressionStream);

        Console.WriteLine("Compressed from {0} to {1} bytes.",
            assignedUsersStream.Length.ToString(),
            resultStream.Length.ToString());
    }
}            

the thing is that resultStream is always empty!

What am I doing wrong here?


Solution

  • Put your verification WriteLine outside of the using. The buffers haven't been flushed yet.

    using (DeflateStream compressionStream = new DeflateStream(resultStream, CompressionLevel.Optimal))
    {
        assignedUsersStream.CopyTo(compressionStream);
    
        //Console.WriteLine("Compressed from {0} to {1} bytes.",
        //       assignedUsersStream.Length.ToString(), resultStream.Length.ToString());
    }
    
    Console.WriteLine("Compressed from {0} to {1} bytes.",
         assignedUsersStream.Length, resultStream.ToArray().Length);
    

    And aside, you don't need all those ToString()s in a writeline.

    PS: All a BinaryFormatter does with a string is write the bytes with length prefix. If you don't need the prefix (my guess), it could become:

    string users = "";//Really long string goes here
    byte[] result;  
    
    using (MemoryStream resultStream = new MemoryStream())
    {
        using (DeflateStream compressionStream = new DeflateStream(resultStream,
                 CompressionLevel.Optimal))
        {
            byte[] inBuffer = Encoding.UTF8.GetBytes(users);
            compressionStream.Write(inBuffer, 0, inBuffer.Length);
        }
        result = resultStream.ToArray();
    }
    

    The reverse is just as easy but you'll need an estimate of the maximum length to create the read-buffer:

    string users2 = null;
    
    using (MemoryStream resultStream = new MemoryStream(result))
    {
        using (DeflateStream compressionStream = new  DeflateStream(resultStream,
                CompressionMode.Decompress))
        {
            byte[] outBuffer = new byte[2048];   // need an estimate here
            int length = compressionStream.Read(outBuffer, 0, outBuffer.Length);
            users2 = Encoding.UTF8.GetString(outBuffer, 0, length);                        
        }                    
    }