Como localizar uma sequência de valores (especificamente, bytes) dentro de uma coleção maior em .NET

StackOverflow https://stackoverflow.com/questions/2345304

  •  23-09-2019
  •  | 
  •  

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?

Foi útil?

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top