我希望用{0}替换List<byte>
中所有其中一个神奇的2字节包:
{0xF8,0x00} - &gt;替换为0xF8
{0xF8,0x01} - &gt;替换为0xFB
{0xF8,0x02} - &gt;替换为0xFD
{0xF8,0x03} - &gt;替换为0xFE
例如:
List<byte> message
= new List<byte> { 0xFF, 0xFF, 0xFB, 0xF8, 0x00, 0xF8, 0x01, 0xF8, 0x02, 0xF8, 0x03, 0xFE };
// will be converted to:
List<byte> expected
= new List<byte> { 0xFF, 0xFF, 0xFB, 0xF8, 0xFB, 0xFD, 0xFE, 0xFE };
到目前为止,这是我的解决方案,但是我不喜欢它,因为它的可读性非常糟糕:
public static void RemoveEscapeSequences(List<byte> message)
{
// skipped parameter checks
for (int index = 0; index < message.Count - 1; ++index)
{
if (message[index] == 0xF8)
{
// found an escaped byte, look at the following byte to determine replacement
switch (message[index + 1])
{
case 0x0:
message[index] = 0xF8;
message.RemoveAt(index + 1);
break;
case 0x1:
message[index] = 0xFB;
message.RemoveAt(index + 1);
break;
case 0x2:
message[index] = 0xFD;
message.RemoveAt(index + 1);
break;
case 0x3:
message[index] = 0xFE;
message.RemoveAt(index + 1);
break;
}
}
}
}
是否有更短的解决方案,可读性更高?
答案 0 :(得分:3)
你可以做这样的事情 - 虽然会稍微慢一些:
public static void RemoveEscapeSequences(List<byte> message)
{
var replaceBytes = new Dictionary<byte, byte>()
{
{0x00, 0xF8}, {0x01, 0xFB}, {0x02, 0xFD}, {0x03, 0xFE}
};
// skipped parameter checks
for (int index = 0; index < message.Count - 1; ++index)
{
if (message[index] == 0xF8)
{
if(replaceBytes.ContainsKey(message[index + 1]))
{
message[index] = replaceBytes[message[index + 1]];
message.RemoveAt(index + 1);
}
}
}
}
答案 1 :(得分:2)
您可以使用以下扩展方法:
public static IEnumerable<byte> Escape(this IEnumerable<byte> source)
{
if (source == null)
throw new ArgumentNullException("source");
using (var enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
byte current = enumerator.Current;
if (current != 0xF8)
{
yield return current;
continue;
}
if (!enumerator.MoveNext())
yield return current;
byte next = enumerator.Current;
switch (next)
{
case 0x00: yield return 0xF8; break;
case 0x01: yield return 0xFB; break;
case 0x02: yield return 0xFD; break;
case 0x03: yield return 0xFE; break;
default:
yield return current;
yield return next;
break;
}
}
}
}
用法:
List<byte> result = message.Escape().ToList();
foreach(var b in message.Escape())
Console.Write("0x{0:x} ", b);
答案 2 :(得分:1)
这是一个非常简单/易懂的版本,也应该是高效的:
private static List<byte> ComputeBytes(List<byte> input)
{
byte magicValueFirstByte = 0xF8;
var secondByteToBeReplaced = new List<byte> { 0x00, 0x01, 0x02, 0x03 };
var replacements = new List<byte> { 0xF8, 0xFB, 0xFD, 0xFE };
var output = new List<byte>();
for (int i = 0; i < input.Count; i++)
{
var currentValue = input[i];
if (currentValue == magicValueFirstByte && i < input.Count - 1)
{
int index = secondByteToBeReplaced.IndexOf(input[i + 1]);
if (index >= 0)
{
// Then when must replace
output.Add(replacements[index]);
// Skip next item
i++;
continue;
}
}
// Won't replace value, so add current one
output.Add(currentValue);
}
return output;
}
答案 3 :(得分:1)
为什么不将替换字节放在一个小数组中?
private static byte[] EscapeBytes = new byte[]
{
/* 0x00 */ 0xF8,
/* 0x01 */ 0xFB,
/* 0x02 */ 0xFD,
/* 0x03 */ 0xFE
};
然后你可以简单地索引数组:
public static List<byte> RemoveEscapeSequences(List<byte> message)
{
List<byte> result = new List<byte>(message.Count);
bool escape = false;
foreach (byte value in message)
{
if (escape)
{
escape = false;
// Replace the byte. NOTE 1!
result.Add(EscapeBytes[value]);
}
else if (value == 0xF8)
{
// Started an escape sequence.
escape = true;
}
else
{
// Just add the byte.
result.Add(value);
}
}
return result;
}
通过将字节添加到容量已足以保存结果的新列表中,您甚至可以获得更高的性能和更高的可读性。
注1 :当0xF8
转义字节后的字节不在0和3之间时,将发生IndexOutOfRangeException
。如果你在意,你将不得不添加一个小的检查来查看字节值是否在范围内,并决定如果不是这样做(不替换字节,删除转义,抛出异常)。