C#编码文本RLE方法

本文关键字:方法 RLE 文本 编码 | 更新日期: 2023-09-27 18:24:41

我试图通过"删除"重复的字节来打包给定的字节数组,类似于以下内容:

  1. 入口255 1 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

int列表:1 2 6 6 6 6

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

有人能为我指明正确的方向吗?

C#编码文本RLE方法

您的实现存在一些问题:

  1. 解码是不可能的,因为不同的输入(如1 1 1 14 1)产生相同的输出4 1

  2. 如果相同的项目出现次数超过255255 == Byte.MaxValue)次怎么办?

  3. 最好使用通用IEnumerable<Byte>而不是concrete List<Byte>

  4. 您不需要任何缓冲区,只需要计数最后一个项目。

    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));

您永远不会到达这里

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

因为它被放置在倒置的if 内部

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

因此,您永远不会将计数器添加到数组