2013-04-25 65 views
1

我使用下面的代码来压缩2个字符串,它在压缩中运行良好。但是,当我尝试解压缩第二个字符串时,如果第一个字符串很短(大约4个字符),我得到的块长度与其补充异常不匹配。 下面是我用压缩类:c中的压缩字符串#

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(); 
    } 
} 

}

我得到的线DecompressString方法例外:

while ((readBytes = gZipStream.Read(byteArray, 0, byteArray.Length)) != 0) 
+0

内置.NET的通货紧缩算法是片状的,在任何情况下不建议 - 我不知道它甚至已经提高了在新的版本(任何人都可以澄清?)我会说使用SharpZipLib或类似的东西,只为初学者。 – 2013-04-25 11:41:22

+0

那是什么意思,格兰特?抱歉,我是压缩算法的新手.. SharpZipLib会解决我的问题吗? – user1477701 2013-04-25 11:44:47

+0

我已经使用.NET内置的压缩​​算法取得了巨大的成功。核心,它们对于直接控制的数据进行压缩/解压缩非常有用。 – dblood 2013-04-25 13:41:01

回答

1

你的压缩和解压方法应该接受并返回字节阵列。如果您随后需要生成字符串输出,则可以将字节数组转换为base64字符串。

例如:

// 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); 

重命名,并相应地调整你的压缩()和解压()方法。如果你真的想要一个严格使用字符串的类,在你的方法中嵌入Base 64编码/解码的逻辑。但是,如果您的类直接使用'byte []`,那么您的代码在其他情况下将更加灵活和可重用。

+0

非常感谢dblood – user1477701 2013-04-26 04:07:24

+0

不客气。如果答案让你的代码成功运行,你能接受答案吗?祝你好运! – dblood 2013-04-26 13:54:57

2

对于其他正在接收错误消息“块长度与其补码不匹配”的其他人,如果您尝试解压缩未压缩的文件,则可能会发生这种情况。

1

我得到相同的“块长度与其补码不匹配”。 System.IO.InvalidDataException。

我发现这样的信息:http://yvanrodrigues.com/content/block-length-does-not-match-its-complement

它指出:“第一快进2个字节有一个在瘪文件的开头两个字节签名0x789c。”

它应该工作,如果你跳过这2个字节。

更多信息: What does a zlib header look like?.Net zlib inflate with .Net 4.5

+0

你刚刚救了我的命,花了一天的时间才找到这个跳过两个字节。 – 2017-12-10 21:01:10