2013-02-05 14 views
7

Ho un array di byte di lunghezza fissa lungo 1250 byte. Può contenere i seguenti tipi di dati:Array di byte di analisi contenente diversi tipi di dati

  • Oggetto A che consiste di 5 byte. Il primo byte contiene la lettera "A" ei quattro byte successivi memorizzano un numero intero compreso tra 1 e 100000.

  • L'oggetto B costituito da 2 byte. Il primo byte contiene la lettera "B" e il byte successivo contiene un numero intero compreso tra 1 e 100.

  • Oggetto C composto da 50 byte. Tutti i 50 byte sono utilizzati per memorizzare una stringa ASCII con codifica che solo consistere numeri ei seguenti caratteri: - + (e)

Non so quanti di ogni tipo di oggetto sono nell'array di byte, ma so che sono raggruppati insieme (oggetto B, oggetto B, oggetto A, oggetto A, oggetto A, oggetto C, ecc.). La maggior parte delle volte quando analizzo un array di byte, l'array contiene i dati di un tipo (tutti gli oggetti sono Object A, ad esempio), quindi so esattamente quanti byte ogni item è composto e faccio un solo loop attraverso l'array che processa i byte . In questo caso, ho tre diversi tipi di dati che sono tutte diverse lunghezze. Stavo pensando che avrei dovuto fare qualcosa di simile:

int offset = 0; 
while (offset <= 1250) 
{ 
    string objectHeader = Encoding.ASCII.GetString(byteArray, offset, 1); 

    if (objectHeader.Equals("A")) 
    { 
     // read 4 more bytes and then convert into int value (1 - 100000) 
     index += 5; 
    } 
    else if (objectHeader.Equals("B")) 
    { 
     // read 1 more byte and then convert into int value (1 - 100) 
     index += 2; 
    } 
    else 
    { 
     // read 49 more bytes and then convert into a string 
     index += 50; 
    } 
} 

C'è un modo migliore per farlo?

+2

Cosa succede se la stringa racchiusa in un'istanza di classe C inizia con un carattere "B"? Come saprai come decomprimerlo? Devi emettere qualche tipo di informazione sul tipo. – Matt

+2

Queste informazioni sono in fase di archiviazione o sono dati preesistenti che stai tentando di caricare? Chiedo perché ci sono modi molto più semplici per archiviare i dati rispetto agli array di byte. – sircodesalot

+0

@Matt Non sono riuscito a dire che la stringa rappresentata dall'oggetto C sarà composta solo da numeri. Se così non fosse, comunque, che tipo di informazioni di tipo suggeriresti? – user685869

risposta

7

Beh, sembra che ci sia un po 'di confusione con offset e indice, forse si dovrebbe usare un ciclo for:

for(int index = 0; index < 1250; index++) 
{ 
    switch(byteArray[index]) 
    { 
     case (byte)'A': 
      index++; 
      int value = BitConverter.ToInt32(byteArray, index); 
      index += 4; 
      break; 

     case (byte)'B': 
      index++; 
      // Read the next byte as integer. 
      int value = (int)byteArray[index]; 
      index++; 
      break; 

     case (byte)'C': // string. 
      index++; 
      // Read the next 49 bytes as an string. 
      StringBuilder value = new StringBuilder(49); 
      for(int i = index; i < index + 49; index++) 
      { 
       if (byteArray[i] == 0) break; 
       value.Append(Converter.ToChar(byteArray[i])); 
      } 
      index+= 49; 
      break; 

     case 0: // Finished. 
      index = 1250; 
      break; 
     default: 
      throw new InvalidArgumentException("Invalid byte array format"); 
    } 
} 

Come vedi se non ci sono più oggetti? Nel mio esempio suggerisco che termina con un '\ 0'.

Buona fortuna con la tua ricerca.

+0

Grazie per il suggerimento. Ho aggiornato la mia domanda originale per chiarire che la stringa memorizzata nell'oggetto C sarà composta solo da numeri e caratteri - + (e) – user685869

+0

Non ho un buon modo per sapere che non ci sono più oggetti senza elaborare l'intero byte array. – user685869

+0

Probabilmente non è necessario analizzare l'intero array di byte perché si colpisce un oggetto che non corrisponde al proprio formato. EG: oggetto B, maggiore di 100; L'oggetto C contiene un carattere diverso da numeri e caratteri ASCII: - + (e). Immagino che se si tratta di un dispositivo hardware lo riempirà comunque con 0x00s in modo tale da colpire una stringa di 50 caratteri che non convalida e non si interrompe. – Cashley

2
 int offset = 0; 
     while (offset <= 1250) 
     { 

     switch (byteArray[offset]) 
     { 
      case (byte)'A': 
      //read other data .. 
      offset += 5; 
      break; 
      case (byte)'B': 
      //read other data .. 
      offset += 2; 
      break; 
      case (byte)'C': 
      //read other data .. 
      offset += 50; 
      break; 
      default: 
      //error 
      break; 
     } 
     } 

O un'altra variante con lettore di binario:

 var reader = new BinaryReader(new MemoryStream(byteArray), Encoding.ASCII); 
     while (reader.BaseStream.Position < reader.BaseStream.Length) 
     { 
     switch(reader.ReadChar()) 
     { 
      case 'A': 
      { 
       var i = reader.ReadInt32(); 
       return new TypeA(i); 
      } 
      break; 
      case 'B': 
      { 
       var i = reader.ReadByte(); 
       return new TypeB(i); 
      } 
      break; 
      case 'C': 
      { 
       var chars = reader.ReadChars(49); 
       return new TypeC(new string(chars.TakeWhile(ch => ch != 0).ToArray())); 
      } 
      break; 
     } 

     }