2010-02-26 10 views
5

Je dois analyser les octets d'un fichier de sorte que je prenne seulement les données après qu'une certaine séquence d'octets a été identifiée. Par exemple, si la séquence est tout simplement 0xFF (un octet), alors je peux utiliser LINQ sur la collection:Comment localiser une séquence de valeurs (en particulier, octets) dans une collection plus grande dans .NET

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

Mais est-il une façon élégante de détecter une séquence multi-octets - par exemple 0xFF, 0xFF - en particulier celui qui revient en arrière au cas où il commence à avoir une fausse correspondance positive?

Répondre

1

Je ne connais aucun moyen intégré; Comme d'habitude, vous pouvez toujours écrire votre propre méthode d'extension. Voici une sur le dessus de ma tête (il peut y avoir des moyens plus efficaces pour la mettre en œuvre):

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

Je vais devoir vérifier pour vous assurer que cela est correct, mais il devrait vous donner l'idée de base; parcourir les éléments, suivre la dernière séquence de valeurs récupérées, définir un indicateur lorsque la séquence est trouvée et, une fois l'indicateur défini, commencer à renvoyer chaque élément suivant. Editer - J'ai fait un test, et cela fonctionne correctement. Voici un code de test:

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

Si vous convertissez vos octets en une chaîne, vous pouvez profiter de la myriade de fonctions de recherche qui y sont intégrées, même si les octets avec lesquels vous travaillez ne sont pas réellement des caractères au sens traditionnel.

+0

N'êtes-vous pas à vous soucier de ce que .NET pourrait supposer sur l'encodage et ce qui donnerait des résultats erronés? – thelsdj

+0

Je crois que tant que vous êtes à la recherche d'une séquence d'octets exacte, l'encodage ne va pas vraiment importer (tant que la source et la séquence de recherche sont dans le même encodage). Vous pouvez utiliser la classe ASCIIEncoding pour vous aider à effectuer des conversions. – MikeP