C#编码文本RLE方法
C# encoding text RLE method
我正在尝试通过 'removing' 重复字节来打包给定的字节数组,如下所示:
- 入口 255 1 1 4 4 4 4 4 200 15 10
- 输出 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
和4 1
产生相同的输出:4 1
- 如果相同的项目出现超过 255(
255 == Byte.MaxValue
)次怎么办?
- 最好使用通用
IEnumberable<Byte>
然后 concrete List<Byte>
您不需要任何 缓冲区,只需 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));
我正在尝试通过 'removing' 重复字节来打包给定的字节数组,如下所示:
- 入口 255 1 1 4 4 4 4 4 200 15 10
- 输出 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
和4 1
产生相同的输出:4 1
- 如果相同的项目出现超过 255(
255 == Byte.MaxValue
)次怎么办? - 最好使用通用
IEnumberable<Byte>
然后concrete List<Byte>
您不需要任何 缓冲区,只需 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));