Как найти последовательность значений (в частности, байтов) в большей коллекции в .NET - PullRequest
5 голосов
/ 27 февраля 2010

Мне нужно проанализировать байты из файла, чтобы я брал данные только после того, как определенная последовательность байтов была идентифицирована. Например, если последовательность просто 0xFF (один байт), я могу использовать LINQ для коллекции:

byte[] allBytes = new byte[] {0x00, 0xFF, 0x01};
var importantBytes = allBytes.SkipWhile(byte b => b != 0xFF);
// importantBytes = {0xFF, 0x01}

Но есть ли элегантный способ обнаружения многобайтовой последовательности - например, 0xFF, 0xFF - особенно тот, который возвращается в случае ложного положительного совпадения?

Ответы [ 3 ]

1 голос
/ 27 февраля 2010

Я не знаю ни одного встроенного способа; как обычно, вы всегда можете написать свой собственный метод расширения. Вот один из них (у меня могут быть более эффективные способы его реализации):

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

Я должен проверить, чтобы убедиться, что это правильно, но это должно дать вам основную идею; перебирайте элементы, отслеживайте последнюю последовательность найденных значений, устанавливайте флаг, когда последовательность найдена, и после установки флага начинайте возвращать каждый последующий элемент.

Редактировать - я запустил тест, и он работает правильно. Вот некоторый тестовый код:

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();
}
1 голос
/ 27 февраля 2010

Если вы конвертируете свои байты в строку, вы можете воспользоваться множеством встроенных в нее функций поиска, даже если байты, с которыми вы работаете, на самом деле не являются символами в традиционном смысле.

0 голосов
/ 27 февраля 2010

Просто немного теории; это обычная языковая проблема. Вы можете использовать механизм регулярных выражений для его обнаружения. Первый гугл-запрос "регулярное выражение в потоке" найден

http://codeguru.earthweb.com/columns/experts/article.php/c14689

...