Parsing byte array that contains different types of data
Solution 1
Well, there seems to be a little confusion with offset and index, maybe you should be using a for-loop:
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");
}
}
How do you see if there is no more objects? In my example I suggest it ends with a '\0'.
Good luck with your quest.
Solution 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;
}
}
Or another variant with binary reader:
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;
}
}
bmt22033
Updated on June 24, 2022Comments
-
bmt22033 almost 2 years
I have a fixed-length byte array that is 1250 bytes long. It may contain the following types of data:
Object A which consists of 5 bytes. The first byte contains the letter "A" and the next four bytes store an integer from 1 - 100000.
Object B which consists of 2 bytes. The first byte contains the letter "B" and the next byte contains an integer from 1 - 100.
Object C which consists of 50 bytes. All 50 bytes are used to store an ASCII-encoded string which will only consist of numbers and the following characters: - + ( and )
I don't know how many of each object type are in the byte array but I do know that they are grouped together (Object B, Object B, Object A, Object A, Object A, Object C, etc.). Most of the time when I parse a byte array, the array contains data of one type (all items are Object A, for example) so I know exactly how many bytes each item is comprised of and I just loop through the array processing the bytes. In this case, I have three different types of data that are all different lengths. I was thinking that I would need to do something like this:
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; } }
Is there a better way of doing this?
-
bmt22033 over 11 yearsThanks for the suggestion. I have updated my original question to clarify that the string stored in Object C will only consists of numbers and the characters - + ( and )
-
bmt22033 over 11 yearsI don't have a good way to know that there are no more objects without processing the whole byte array.
-
Cashley over 11 yearsPresumably you don't have to parse the entire byte array because you will hit an object which doesn't match your format. EG: Object B, greater than 100; Object C, contains a character other than ASCII numbers and characters: - + ( and ). I'd imagine if this is a hardware device it will just pad it with 0x00s anyway so you'll hit a 50-character string which doesn't validate and break there.