【问题标题】:compression string in c#c#中的压缩字符串
【发布时间】:2013-04-25 11:01:51
【问题描述】:

我正在使用以下代码压缩 2 个字符串,它在压缩方面效果很好。但是,当我尝试解压缩第二个字符串并且如果第一个字符串很短(大约 4 个字符)时,我得到块长度与其补码异常不匹配。 这是我用于压缩的类:

    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)

【问题讨论】:

  • .NET 的内置通缩算法是不稳定的,无论如何都不推荐使用 - 我不确定它在最近的版本中是否得到了改进(有人可以澄清吗?)我会说使用SharpZipLib 或类似的东西,仅供初学者使用。
  • 你说的格兰特是什么意思?抱歉,我是压缩算法的新手。SharpZipLib 能解决我的问题吗?
  • 我已成功使用 .NET 内置压缩算法。从本质上讲,它们对于压缩/解压缩您直接控制的数据很有用。

标签: c# compression


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您的 Compress 和 Decompress 方法应该接受并返回字节数组。如果您需要生成字符串输出,您可以将字节数组转换为 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);
    

    相应地重命名和调整 Compress() 和 Decompress() 方法。如果您真的想要一个严格使用字符串的类,请在您的方法中嵌入 Base 64 编码/解码的逻辑。但是,如果您的类直接与 'byte[]` 一起使用,您的代码将更加灵活且可在其他实例中重用。

    【讨论】:

    • 不客气。如果答案使您的代码成功运行,您可以接受答案吗?祝你好运!
    【解决方案3】:

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

    我找到了这个信息:http://yvanrodrigues.com/content/block-length-does-not-match-its-complement

    它声明:“先向前搜索 2 个字节。在压缩文件的开头有一个 2 字节签名 0x789c。”

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

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

    【讨论】:

    • 你刚刚救了我的命,花了一天时间才找到这个跳过两个字节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 2011-11-12
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多