2013-04-29 6 views
5

Mam tablicy bajtów, który wygląda mniej więcej tak:Jak prawidłowo wyszukiwać i analizować tablicę używając sekwencję elementów jako cel

byte[] exampleArray = new byte[] 
         { 0x01, 0x13, 0x10, 0xe2, 0xb9, 0x13, 0x10, 0x75, 0x3a, 0x13 }; 

mój koniec celem jest rozbicie tej tablicy do każdej chwili sub Array I zobacz sekwencję { 0x13, 0x10 }. Więc mój pożądany rezultat na przykład tablicy byłoby:

{ 0x01 } 
{ 0xe2, 0xb9 } 
{ 0x75, 0x3a, 0x13 } 

Idealnie Chciałbym również wiedzieć, że ostateczna tablicą, { 0x75, 0x3a, 0x13 }, nie kończy się sekwencją wyszukiwania tak, że mogę pracować z tym jako specjalny walizka.

Jakieś przemyślenia na temat najlepszego podejścia?

+0

Co się stanie, jeśli skonwertujesz tablicę ascii i użyjesz string.split? Coś w stylu 'Encoding.ASCII.GetString (exampleArray) .Split (...)' – Vladimir

+0

Zobacz: http://stackoverflow.com/a/4617264/848330 – nmat

+1

'string delimiter = Encoding.ASCII.GetString (new byte [ ] {0x13, 0x10}); ' – Vladimir

Odpowiedz

1
List<byte[]> Split(byte[] bArray) 
     { 
      List<byte[]> result = new List<byte[]>(); 
      List<byte> tmp = new List<byte>(); 
      int i, n = bArray.Length; 
      for (i = 0; i < n; i++) 
      { 
       if (bArray[i] == 0x13 && (i + 1 < n && bArray[i + 1] == 0x10)) 
       { 
        result.Add(tmp.ToArray()); 
        tmp.Clear(); 
        i++; 
       } 
       else 
        tmp.Add(bArray[i]); 
      } 
      if (tmp.Count > 0) 
       result.Add(tmp.ToArray()); 
      return result; 
     } 

Ostatnia tablica nie może kończyć się kolejno, każdy splited części nie oddziela separatora. Może się zdarzyć tylko bajt 0x13, więc jeśli jest to dla ciebie ważne, możesz sprawdzić ostatni bajt ostatniej tablicy podrzędnej.

+0

To spowoduje, że indeks zniknie z błędu; musisz upewnić się, że twoja pętla 'for' nie przechodzi aż do końca, jeśli zaznaczysz" następny "element w ciele. – Servy

+0

Przyjąłem tę odpowiedź, ponieważ jest najbliżej tego, co zrobiłem. Dziękuję Ci. –

1

Jak o czymś takim, który powinien działać w ogólnym przypadku (oczywiście z lepszej kontroli błędów!):

using System; 
using System.Collections.Generic; 
using System.Linq; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     byte[] exampleArray = new byte[] { 1, 2, 3, 4, 5, 2, 3, 6, 7, 8 }; 

     var test = exampleArray.PartitionBySubset(new byte[] { 2, 3 }).ToList(); 
    } 
} 

public static class Extensions 
{ 
    public static IEnumerable<IEnumerable<T>> PartitionBySubset<T>(this IEnumerable<T> sequence, IEnumerable<T> subset) where T : IEquatable<T> 
    { 
     // Get our subset into a array so we can refer to items by index and so we're not iterating it multiple times. 
     var SubsetArray = subset.ToArray(); 
     // The position of the subset array we will check 
     var SubsetArrayPos = 0; 
     // A list to hold current items in the subsequence, ready to be included in the resulting sequence 
     var CurrentList = new List<T>(); 

     foreach (var item in sequence) 
     { 
      // add all items (ones part of the subset will be removed) 
      CurrentList.Add(item); 
      if (item.Equals(SubsetArray[SubsetArrayPos])) 
      { 
       // This item is part of the subset array, so move to the next subset position 
       SubsetArrayPos++; 
       // Check whether we've checked all subset positions 
       if (SubsetArrayPos == SubsetArray.Length) 
       { 
        // If so, then remove the subset items from the current list 
        CurrentList.RemoveRange(CurrentList.Count - SubsetArray.Length, SubsetArray.Length); 
        // Reset the position 
        SubsetArrayPos = 0; 

        // Only return the list if it's not empty (the main list could start with a subset) 
        if (CurrentList.Count != 0) 
        { 
         // Return the list we have now since it's been ended. 
         yield return CurrentList; 
         // Create a new list ready for more items 
         CurrentList = new List<T>(); 
        } 
       } 
      } 
      else 
      { 
       // This item isn't part of the subset, so next time check the start. 
       SubsetArrayPos = 0; 
      } 
     } 

     // If we get to the end and have some items to return, then return them. 
     if (CurrentList.Count != 0) 
      yield return CurrentList; 
    } 
} 
0
string example = Encoding.ASCII.GetString(exampleArray); 
string delimiter = Encoding.ASCII.GetString(new byte[] { 0x13, 0x10 }); 
string[] result = example.Split(new string[] { delimiter}); 
string ending = Encoding.ASCII.GetString(new byte[] { 0x75, 0x3a, 0x13 }); 
bool ends = example.EndsWith(ending); 
0

Kontynuowałbym sprawdzanie bieżącego i poprzedniego elementu tablicy. Tak:

int[] data = ...; 

// start from second byte, to be able to touch the previous one 
int i = 1; 
while (i < data.Length) 
{ 
    if (data[i-1] == 0x13 && data[i] == 0x10) 
    { 
     // end of subarray reached 
     Console.WriteLine(); 
     i+=2; 
    } 
    else 
    { 
     // output the previous character, won't be used in the next iteration 
     Console.Write(data[i-1].ToString("X2")); 
     i++; 
    } 
} 

// process the last (or the only) byte of the array, if left 
if (i == data.Length) 
{ 
    // apparently there wasn't a delimiter in the array's last two bytes 
    Console.Write(data[i-1].ToString("X2")); 
    Console.WriteLine(" - no 0x13 010"); 
} 

Uwaga: wyjście konsoli ze względu na demonstracji. Zastąp rzeczywistym przetwarzaniem danych.

Powiązane problemy