1

I am using the following code to compress 2 strings, it works well in compression. However, when I try to decompress the second strings and if the first one is short (about 4 characters) I got Block length does not match with its complement exception. Here is the class I used for compression:

    using System;
    using System.IO;
    using System.IO.Compression;
    using System.Text;

    namespace CompressString {
    internal static class StringCompressor
{
    /// <summary>
    /// Compresses the string.
    /// </summary>
    /// <param name="text">The text.</param>
    /// <returns></returns>
    public static string CompressString(string value)
    {
        //Transform string into byte[] 
        byte[] byteArray = new byte[value.Length];
        int indexBA = 0;
        foreach (char item in value.ToCharArray())
        {
            byteArray[indexBA++] = (byte)item;
        }

        //Prepare for compress
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        System.IO.Compression.GZipStream sw = new System.IO.Compression.GZipStream(ms,
        System.IO.Compression.CompressionMode.Compress);

        //Compress
        sw.Write(byteArray, 0, byteArray.Length);
        //Close, DO NOT FLUSH cause bytes will go missing...
        sw.Close();

        //Transform byte[] zip data to string
        byteArray = ms.ToArray();
        System.Text.StringBuilder sB = new System.Text.StringBuilder(byteArray.Length);
        foreach (byte item in byteArray)
        {
            sB.Append((char)item);
        }
        ms.Close();
        sw.Dispose();
        ms.Dispose();

        return sB.ToString();
    }

    /// <summary>
    /// Decompresses the string.
    /// </summary>
    /// <param name="compressedText">The compressed text.</param>
    /// <returns></returns>
    public static string DecompressString(string sData)
    {
        byte[] byteArray = new byte[sData.Length];

        int indexBa = 0;
        foreach (char item in sData)
            byteArray[indexBa++] = (byte)item;

        MemoryStream memoryStream = new MemoryStream(byteArray);
        GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress);

        byteArray = new byte[1024];

        StringBuilder stringBuilder = new StringBuilder();

        int readBytes;
        while ((readBytes = gZipStream.Read(byteArray, 0, byteArray.Length)) != 0)
        {
            for (int i = 0; i < readBytes; i++) stringBuilder.Append((char)byteArray[i]);
        } gZipStream.Close(); memoryStream.Close(); gZipStream.Dispose(); memoryStream.Dispose(); return stringBuilder.ToString();
    }
}

}

I got the exception in DecompressString method in the line:

while ((readBytes = gZipStream.Read(byteArray, 0, byteArray.Length)) != 0)
3
  • The built-in deflation algorithm of .NET is flaky and not recommended in any case - I'm not sure it's even been improves in more recent versions (can anyone clarify?) I'd say use SharpZipLib or something similar, just for starters. Commented Apr 25, 2013 at 11:41
  • What do you mean by that Grant? sorry but I am novice in compression algorithms.. Will SharpZipLib solve my problem? Commented Apr 25, 2013 at 11:44
  • I've used the .NET built-in compression algorithms with great success. At the core, they are useful for compressing/decompressing data that you control directly. Commented Apr 25, 2013 at 13:41

3 Answers 3

2

For others that are receiving the error message "Block length does not match with its complement", this can occur if you are trying to decompress a file that was not compressed.

Sign up to request clarification or add additional context in comments.

Comments

1

Your Compress and Decompress methods should accept and return byte arrays. If you then are required to produce string output you can convert the byte array to a base64 string.

For example:

// compress some string data
string stringData = GetSomeStringData();

// assumes the string data is UTF8 string - would work for ASCII encoding as well
byte[] uncompressedData = Encoding.UTF8.GetBytes(stringData);

byte[] compressedData = StringCompressor.Compress(uncompressedData);

// produce base64 encode string of compressed data
string compressedString = Convert.ToBase64String(compressedData);

// decompress base64 encoded string 
// first convert to byte array
byte[] dataToDecompress = Convert.FromBase64String(compressedString);

byte[] decompressedData = StringCompressor.Decompress(dataToDecompress);

// encode decompressed data as a UTF8 encoded string
string decompressedString = Encoding.UTF8.GetString(decompressedData);

Rename and Tweak your Compress() and Decompress() methods accordingly. If you really wanted to have a class that strictly worked with strings, embed the logic of the Base 64 encoding/decoding in your methods. However, if your class works directly with 'byte[]` your code will be much more flexible and reusable in other instances.

1 Comment

you're welcome. If the answer got your code running successfully, can you accept the answer? Good luck!
1

I get the same "Block length does not match with its complement." System.IO.InvalidDataException.

I've found this information: http://yvanrodrigues.com/content/block-length-does-not-match-its-complement

It states: "Seek forward 2 bytes first. There is a two byte signature 0x789c at the beginning of the deflated file."

It should work if you skip these 2 bytes.

Further information: What does a zlib header look like? and .Net zlib inflate with .Net 4.5

1 Comment

You just saved my life and a it took one day to find this skip two bytes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.