代码之家  ›  专栏  ›  技术社区  ›  user333306

C语言中的通用字符串编码器#

c#
  •  3
  • user333306  · 技术社区  · 15 年前

    我需要的非常简单,但是在我发明轮子之前,我想知道在框架中是否已经存在类似的东西。

    我想从预定义的字符表中编码(和解码)字符串。我有很多字符串,只包含几个字符。下面是我要编码的字符串:

    cn=1;pl=23;vf=3;vv=0

    这个字符串的大小是20个字符,所以是20个字节。

    总共11个字符。所以每个字符只能用4位编码不是吗?将总字节数减少到10。

    在.NET中是否存在可以在参数和引用表数组中使用字符串并返回编码字节的现有方法?

    string input=“cn=1;pl=23;vf=3;vv=0”;

    string decoded=someClass.Decode(编码,引用);

    Assert.AreEqual(输入,解码);

    7 回复  |  直到 15 年前
        1
  •  2
  •   Hans Passant    15 年前

    任何压缩算法使用 Huffman encoding

        2
  •  2
  •   Guffa    15 年前

    疑问句。。。框架中没有任何内容,但可以这样做:

    public static byte[] Encode(string input, string reference) {
      int size = 1;
      while ((1 << ++size) < reference.Length);
      byte[] result = new byte[(size * input.Length + 7) / 8];
      new BitArray(
        input
        .Select(c => {
          int index = reference.IndexOf(c);
          return Enumerable.Range(0, size).Select(i => (index & (1 << i)) != 0);
        })
        .SelectMany(a => a)
        .ToArray()
      ).CopyTo(result, 0);
      return result;
    }
    
    public static string Decode(byte[] encoded, int length, string reference) {
      int size = 1;
      while ((1 << ++size) < reference.Length);
      return new String(
        new BitArray(encoded)
          .Cast<bool>()
          .Take(length * size)
          .Select((b, i) => new { Index = i / size, Bit = b })
          .GroupBy(g => g.Index)
          .Select(g => reference[g.Select((b, i) => (b.Bit ? 1 : 0) << i).Sum()])
          .ToArray()
      );
    }
    

    代码有点复杂,但那是因为它可以处理每个字符的任何位数,而不仅仅是4位。

    您可以像问题中那样对字符串进行编码,但字符串包含 不同的角色,不是11个:

    string reference = "cn=1;pl23vf0";
    string input = "cn=1;pl=23;vf=3;vv=0";
    
    byte[] encoded = Encode(input, reference);
    

    要解码字符串,您还需要原始字符串的长度,因为无法从编码数据的长度中分辨出来:

    string decoded = Decode(encoded, input.Length, reference);
    

        3
  •  1
  •   LBushkin    15 年前

    没有现成的类可以做到这一点,但是使用 BitArray .NET类。 一旦有了位数组,就可以将其转换为字符串或压缩字节表示形式。

    // modify this as appropriate to divide your original input string...
    public IEnumerable<string> Divide( string s )
    { 
        for( int i = 0; i < s.Length; i += 2 )
            yield return s.Substring( i, 2 );
    }
    
    public IEnumerable<bool> AsBoolArray( byte b )
    {
        var i = 4; // assume we only want 4-bits
        while( i-- > 0 )
        {
            yield return (b & 0x01) != 0;
            b >>= 1;
        }
    }
    
    // define your own mapping table...
    var mappingTable = 
      new Dictionary<string,int>() { {"cn", 1}, {"pl",23}, {"vf",3}, {"vv",0} /*...*/ };
    var originalString = "cncnvfvvplvvplpl";
    
    // encode the data by mapping each string to the dictionary...
    var encodedData = DivideString( originalString ).Select( s => mappingTable[s] );
    // then convert into a bitVector based on the boolean representation of each value...
    // The AsBoolArray() method return the 4-bit encoded bool[] for each value
    var packedBitVector = 
      new BitArray( encodedData.Select( x => AsBoolArray(x) ).ToArray() );
    // you can use BitArray.CopyTo() to get the representation out as a packed int[]
    
        4
  •  1
  •   Poma    15 年前

    我想如果你想把绳子的尺寸减到最小,最好用 System.IO.Compression.GZipStream 在这里。它非常简单,可能会压缩字符串2倍以上。

        5
  •  0
  •   Oded    15 年前

    在基类库中没有类似的东西。你将不得不建立自己的。

    看看 Encoder 系统中的类。文本-某些元素可能有帮助。

        6
  •  0
  •   Will Marcouiller    15 年前

    StringBuilder 有什么帮助吗?

        7
  •  0
  •   Muad'Dib    15 年前

    你可以用CrytpAPI。这是一个很好的例子, including