2013-02-05 63 views
7

我有一个1250字节长的固定长度字节数组。它可能包含以下类型的数据:解析包含不同类型数据的字节数组

  • 对象A由5个字节组成。第一个字节包含 字母“A”,接下来的四个字节存储从1到100000的整数。

  • 对象B由2个字节组成。第一个字节包含字母“B”,下一个字节包含从1到100的整数。

  • 对象C由50个字节组成。所有的50个字节用来存储ASCII编码的字符串,这将和以下字符: - +(和)

我不知道有多少每个对象类型在字节数组中,但我知道它们被组合在一起(对象B,对象B,对象A,对象A,对象A,对象C等)。大多数情况下,当我解析一个字节数组时,数组包含一种类型的数据(例如,所有的项目都是对象A),所以我确切知道每个项目由多少个字节组成,我只是遍历数组处理字节。在这种情况下,我有三种不同类型的数据,都是不同的长度。我在想,我需要这样做:

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

有没有更好的方法来做到这一点?

+2

如果封装在类C实例中的字符串以'B'字符开头会怎么样?你怎么知道如何解开它?你需要发出某种类型的信息。 – Matt

+2

您正在存储此信息,还是您尝试加载的预先存在的数据?我问,因为有比字节数组更容易存储数据的方法。 – sircodesalot

+0

@Matt我没有说对象C所表示的字符串将只包含数字。但是,如果情况并非如此,您会建议哪种类型的信息? – user685869

回答

7

嗯,似乎有点混乱失调和指标,也许你应该用一个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"); 
    } 
} 

你如何看待没有更多的物体?在我的例子中,我建议以'\ 0'结尾。

祝你好运与你的追求。

+0

感谢您的建议。我已经更新了我的原始问题,以澄清存储在对象C中的字符串将只包含数字和字符 - +(和) – user685869

+0

我没有一个很好的方法来知道没有更多的对象没有处理整个字节阵列。 – user685869

+0

大概你不必解析整个字节数组,因为你会碰到一个与你的格式不匹配的对象。 EG:对象B,大于100;对象C包含ASCII数字和字符以外的字符: - +(和)。我想象一下,如果这是一个硬件设备,它只会用0x00填充它,所以你会打到一个50个字符的字符串,它不会验证并在那里打破。 – 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; 
     } 
     } 

或用二进制读取另一种变体:

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

     }