C#压缩短串和长串

时间:2013-04-30 10:45:58

标签: c# compression

我想操纵一个算法来压缩c#中的长字符串和短字符串,我尝试过的所有算法都能够压缩长字符串而不是短字符串(大约5个字符)。代码是:

using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.IO;
using System.Collections;
using System.Text;

namespace CompressString {
internal static class StringCompressor
{
    /// <summary>
    /// Compresses the string.
    /// </summary>
    /// <param name="text">The text.</param>
    /// <returns>compressed string</returns>
    public static string CompressString(string text)
    {
        byte[] buffer = Encoding.Default.GetBytes(text);
        MemoryStream ms = new MemoryStream();
        using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
        {
            zip.Write(buffer, 0, buffer.Length);
        }
        ms.Position = 0;
        byte[] compressed = new byte[ms.Length];
        ms.Read(compressed, 0, compressed.Length);
        byte[] gzBuffer = new byte[compressed.Length + 4];
        System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
        System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
        return Encoding.Default.GetString(gzBuffer);
    }

    /// <summary>
    /// Decompresses the string.
    /// </summary>
    /// <param name="compressedText">The compressed text</param>
    /// <returns>uncompressed string</returns>
    public static string DecompressString(string compressedText)
    {
        byte[] gzBuffer = Encoding.Default.GetBytes(compressedText);
        using (MemoryStream ms = new MemoryStream())
        {
            int msgLength = BitConverter.ToInt32(gzBuffer, 0);
            ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
            byte[] buffer = new byte[msgLength];
            ms.Position = 0;
            using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
            {
                zip.Read(buffer, 0, buffer.Length);
            }
            return Encoding.Default.GetString(buffer);
        }
    }
}}

我在行中的解压缩方法中得到了InvalidDataException(在解码时发现了无效数据): zip.Read(buffer,0,buffer.Length); 你有什么建议吗?

2 个答案:

答案 0 :(得分:0)

您是否有特殊要求需要压缩5个字符? 否则你最终将无需使用CPU和内存:获得5个字符空间的机会非常低(4%减少到4个字符,0.1%减少到3个字符等等,如果字符串可以更少包含不同的大小写,标点符号,特殊字符等。)

答案 1 :(得分:0)

似乎有两个基本问题。一个是错误,一个是长度。

您展示的代码似乎与此处相同: http://dotnet-snippets.com/dns/c-compress-and-decompress-strings-SID612.aspx

我无法证明此代码中是否存在任何错误,但它似乎适用于我尝试过的随机分类字符串(长度各异)。给我们一个代码失败的字符串示例,我们可以进一步调查。

至于长度,代码为字符串长度添加4个字节只是为了开始。所以你压缩长度为5的字符串的几率是zilch。这甚至没有提到理论方面。鸽笼原理基本上是基于这样一个事实,即长串比短串更可能。例如,只有10个一位数字,但有100个两位数字。因此,您无法将所有100个两位数字缩短为一位数。此外,如果您可以压缩任何字符串,您可以重复该过程并将所有字符串压缩到一位。

您可以通过两种方式轻松改善压缩效果。如果你知道你不会存储大字符串,你可以减少存储的字符串长度,例如你可以存储一下是否压缩字符串,如果压缩版本更大则存储未解压缩。它为压缩字符串增加了1位开销,但如果你想要一致性可能会更好。