C#编码文本RLE方法

C# encoding text RLE method

我正在尝试通过 'removing' 重复字节来打包给定的字节数组,如下所示:

  1. 入口 255 1 1 4 4 4 4 4 200 15 10
  2. 输出 1x255 2x1 5x4 1x200 1x15 1x10 => 255 1 1 5 4 200 15 10

如果一个字节重复超过 3 次,我用计数器替换它。

我开始制作一个没有重复值的临时字节列表和出现次数的列表。不过我的计数器有问题:

public static void compressBlock(List<byte> buffer)
    {
        byte marker = buffer.Last();

        int counter = 1;


        byte[] buffer_ar = new byte[buffer.Count];
        buffer_ar = buffer.ToArray();

        List<byte> temp = new List<byte>();
        List<int> tmp = new List<int>();


       int indeks = 0;
            while (true)
            {


                if (buffer_ar[indeks] == buffer_ar[indeks + 1])
                {
                    counter++;

                    if (buffer_ar[indeks] != buffer_ar[indeks + 1])
                    {
                        temp.Add(buffer_ar[indeks]);
                        tmp.Add(counter);
                        //counter = 1;
                    }


                }

                else
                {
                    //counter = 1;
                    temp.Add(buffer_ar[indeks]);
                    tmp.Add(counter);

                }

                indeks++;
                //counter = 1;

                if (buffer_ar.Length -1 <= indeks) { break; }

            }

作为我的输出:

字节列表:255 1 4 200 15 10

整数列表:1 2 6 6 6 6

我知道我必须在某个时候重置计数器,但是当我这样做作为 int 列表的输出时,我有:1 1 1 1 1 1。

有人能指出正确的方向吗?

你永远到不了这里

if (buffer_ar[indeks] != buffer_ar[indeks + 1])

因为里面是倒置if

if (buffer_ar[indeks] == buffer_ar[indeks + 1])

所以你永远不会将计数器添加到数组中

您的实施存在一些问题:

  1. 解码是不可能的,因为不同的输入1 1 1 14 1产生相同的输出4 1
  2. 如果相同的项目出现超过 255255 == Byte.MaxValue)次怎么办?
  3. 最好使用通用 IEnumberable<Byte> 然后 concrete List<Byte>
  4. 您不需要任何 缓冲区,只需 count 最后一项出现。

    public static IEnumerable<Byte> RleEncode(IEnumerable<Byte> source) {
      if (null == source)
        throw new ArgumentNullException("source");
    
      const int threshold = 3;
    
      Byte current = 0;
      int count = 0;
    
      foreach (var item in source) 
        if ((count == 0) || (current == item)) {
          current = item; 
          count += 1;
        }
        else {
          if (count <= threshold)
             for (int i = 0; i < count; ++i)
               yield return current;
          else {
            for (int i = 0; i < count / Byte.MaxValue; ++i) {
              yield return Byte.MaxValue;
              yield return current;
            }
    
            if (count % Byte.MaxValue != 0) {
              yield return (Byte) (count % Byte.MaxValue);
              yield return current;
            }
          }
    
        current = item;
        count = 1;
      }
    
      // Tail
      if (count <= threshold)
        for (int i = 0; i < count; ++i)
           yield return current;
      else {
        for (int i = 0; i < count / Byte.MaxValue; ++i) {
          yield return Byte.MaxValue;
          yield return current;
        }
    
        if (count % Byte.MaxValue != 0) {
          yield return (Byte) (count % Byte.MaxValue);
          yield return current;
        }
      }
    }
    

测试

  List<Byte> source = new List<Byte> {
    255, 1, 1, 4, 4, 4, 4, 4, 200, 15, 10
  };

  // 255 1 1 5 4 200 15 10 
  String test = String.Join(" ", RleEncode(source));