【问题标题】:C# compress short and long stringC#压缩短字符串和长字符串
【发布时间】:2013-04-30 20:10:43
【问题描述】:

我想操纵一种算法来压缩 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); 你有什么建议?

【问题讨论】:

  • 你应该发布一些关于你尝试过的代码,或者至少扩展你的问题。见stackoverflow.com/faq
  • 压缩不能永远保证让一切都更短......而且非常少量的数据压缩很少有效。
  • 示例:如果您有一个类似aaaaa 的字符串,那么您可以将其缩短为类似5a 的字符串。但是如果你有一个像afgdc 这样的字符串,那么就没有真正有意义的方法来通过算法缩短它。您可以制作字典并说1 = "afgdc",然后只提交1,但对方需要知道1 代表什么,因此您还需要提交字典,但您没有任何收获。
  • 以某种方式将许多短字符串组合成1个长字符串,然后压缩。
  • 我有一个最多 1200 个字符的字符串,我不应该将字符串压缩到哪个限制?

标签: c# compression


【解决方案1】:

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

【讨论】:

  • 是的,我有。所以你建议不要压缩这么短的字符串,但是如果我的字符串限制为 1200 个字符,我应该从哪个长度开始压缩?
  • 对不起,我无法回答你:你应该自己测试。制作一个产生不同长度的随机字符串的小代码,然后压缩并比较结果。对每个长度(即 5、10、20 等)执行 100 次并将结果写入 csv,以便您可以在 excel 中打开它并制作图表。它应该会给你一个答案。
【解决方案2】:

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

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

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

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

您可以通过两种方式轻松提高压缩率。如果你知道你不会存储巨大的字符串,你可以减少存储的字符串长度,例如到 2 个字节而不是 4 个。并且您可以存储一些是否压缩字符串,如果压缩版本更大,则将其存储为未压缩。它为压缩字符串增加了 1 位开销,但如果您想要一致性可能会更好。

【讨论】:

  • 例如,此代码压缩单词“头痛”失败
  • 其实我是压缩算法的新手,所以我会非常感谢你的帮助..
  • 嗯,同样的代码对我来说“头痛”。你能显示你调用这个类的代码吗?错误可能在那里。你能解释一下你要压缩的东西吗?它们只是文字吗?句子? GZip 很棒,但不能解决所有问题。例如,如果我们知道只有字母,没有数字或标点符号,我们可以保证压缩它。
猜你喜欢
  • 2019-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-12
  • 1970-01-01
  • 2017-11-11
相关资源
最近更新 更多