Reputation: 147
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)
Upvotes: 1
Views: 5624
Reputation: 48
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
Upvotes: 1
Reputation: 21
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.
Upvotes: 2
Reputation: 1778
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.
Upvotes: 1