Como localizar uma sequência de valores (especificamente, bytes) dentro de uma coleção maior em .NET
Pergunta
Eu preciso analisar os bytes de um arquivo para que eu apenas tome os dados após a identificação de uma certa sequência de bytes. Por exemplo, se a sequência for simplesmente 0xff (um byte), posso usar o LINQ na coleção:
byte[] allBytes = new byte[] {0x00, 0xFF, 0x01};
var importantBytes = allBytes.SkipWhile(byte b => b != 0xFF);
// importantBytes = {0xFF, 0x01}
Mas existe uma maneira elegante de detectar uma sequência de vários bytes - por exemplo, 0xff, 0xff - especialmente um que recua, caso comece a obter uma correspondência falsa positiva?
Solução
Não estou ciente de nenhuma maneira interna; Como de costume, você sempre pode escrever seu próprio método de extensão. Aqui está um do topo da minha cabeça (pode haver maneiras mais eficientes de implementá -lo):
public static IEnumerable<T> AfterSequence<T>(this IEnumerable<T> source,
T[] sequence)
{
bool sequenceFound = false;
Queue<T> currentSequence = new Queue<T>(sequence.Length);
foreach (T item in source)
{
if (sequenceFound)
{
yield return item;
}
else
{
currentSequence.Enqueue(item);
if (currentSequence.Count < sequence.Length)
continue;
if (currentSequence.Count > sequence.Length)
currentSequence.Dequeue();
if (currentSequence.SequenceEqual(sequence))
sequenceFound = true;
}
}
}
Vou ter que verificar para garantir que isso esteja correto, mas deve lhe dar a ideia básica; Iterre através dos elementos, rastreie a última sequência de valores recuperada, defina um sinalizador quando a sequência for encontrada e, assim que o sinalizador estiver definido, comece a retornar cada elemento subsequente.
EDIT - Eu fiz um teste e funciona corretamente. Aqui está algum código de teste:
static void Main(string[] args)
{
byte[] data = new byte[]
{
0x01, 0x02, 0x03, 0x04, 0x05,
0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA
};
byte[] sequence = new byte[] { 0x02, 0x03, 0x04, 0x05 };
foreach (byte b in data.AfterSequence(sequence))
{
Console.WriteLine(b);
}
Console.ReadLine();
}
Outras dicas
Se você converter seus bytes em uma string, poderá aproveitar a infinidade de funções de pesquisa incorporadas a isso, mesmo que os bytes com os quais você esteja trabalhando não sejam realmente personagens no sentido tradicional.
Apenas como um pouco de teoria; Este é um problema de idioma regular. Você pode usar um mecanismo de expressão regular para detectá -lo. O primeiro sucesso do Google para "Expression On Stream" encontrado
http://codeguru.earthweb.com/columns/experts/article.php/c14689