3
votes

Im trying to transport object over TCP to another machine as string. I have decided to use combination of BinaryFormatter, then GZipStream that and then Base64-encode that before sending. On the other end I do the reverse - decode the string, GZipStream decompress it and then finally deserialize it. Only it does not work when I implement it like this. Getting 'Block length does not match with its complement.' exception

        string s = new String('@', 10000);
        string s2 = "";

        string data;

        using (var ms = new MemoryStream())
        {
            using (var gzip = new GZipStream(ms, CompressionMode.Compress))
            {
                var bf = new BinaryFormatter();
                bf.Serialize(gzip, s);

                gzip.Flush();
                ms.Flush();

                data = Convert.ToBase64String(ms.GetBuffer());
            }
        }

        using (var ms = new MemoryStream(Convert.FromBase64String(data)))
        {
            using (var gzip = new GZipStream(ms, CompressionMode.Decompress, true))
            {
                var binaryFormatter = new BinaryFormatter();
                s2 = binaryFormatter.Deserialize(gzip) as string;
            }
        }

        if (s != s2)
        {
            Console.WriteLine("Doesnt match");
        }

Results in Unhandled Exception: System.IO.InvalidDataException: Block length does not match with its complement.

Any idea? What confuses me the most is that when locally I get rid of the Base64 enconding it works fine.

2

2 Answers

2
votes

You need to close the GZipStream before to assigning it to variable data.

...
bf.Serialize(gzip, s);

gzip.Close();

data = Convert.ToBase64String(ms.GetBuffer());
0
votes

The compressed stream was not flushed. Try below and close the stream.

private static byte[] Compress(Stream input)
    {
        using(var compressStream = new MemoryStream())
        using(var compressor = new DeflateStream(compressStream, CompressionMode.Compress))
        {
            input.CopyTo(compressor);
            compressor.Close();
            return compressStream.ToArray();
        }
    }