Answered by:
How to read a few parts from a byte array and not the entire array

Question
-
I am trying to read different parts of a byte array and not the entire array. How would I do this? I would also like to format an array when creating one. An example would be the first few parts a string then some integers. ThanksThursday, May 5, 2011 9:48 PM
Answers
-
The methods of the BitConverter class all accept a byte array and an integer from which to start reading.
The GetString method of Encoding also accepts an array and an index to start reading from.
Let's say you have recieved a blob of data from some device laid out like this:
Message Length (Integer - Integers are 32 bits, so they use 4 bytes)
Message (String - Each character of an ANSI string uses 1 byte)
Padding (some 0s - Often values are aligned to a 4 byte boundary, so there are padding bytes here so that the next field starts at byte 20)
Value (Double - a 64 bit value so it uses 8 bytes)Here's a sample:
00 0D Message Length
01 00 Message Length
02 00 Message Length
03 00 Message Length
04 48 H
05 65 e
06 6C l
07 6C l
08 6F o
09 20 " "
10 57 W
11 6F o
12 72 r
13 6C l
14 64 d
15 0D Cr
16 0A Lf
17 00 Padding
18 00 Padding
19 00 Padding
20 C9 Value
21 76 Value
22 BE Value
23 9F Value
24 0C Value
25 24 Value
26 FE Value
27 40 ValueYou can use the classes mentioned like this to read the values out:
' The message length field starts at index 0:
Dim messageLength As String = BitConverter.ToInt32(bytes, 0)
' The message itself starts at index 4:
Dim message As String = System.Text.ASCIIEncoding.ASCII.GetString(bytes, 4, messageLength)
' The double value starts at index 20:
Dim value As Double = BitConverter.ToDouble(bytes, 20)
' Write the information out to the user:
Console.WriteLine("Message length: " & messageLength)
Console.WriteLine("Message: " & message)
Console.WriteLine("Value: " & value)
- Marked as answer by Kee PoppyModerator Tuesday, May 17, 2011 9:58 AM
Friday, May 6, 2011 6:55 PM -
I am trying to read different parts of a byte array and not the entire array. How would I do this? I would also like to format an array when creating one. An example would be the first few parts a string then some integers. Thanks
Another option is Buffer.BlockCopy which allows you to copy the bytes from one array of one type to another array of another type.
Stephen J Whiteley- Proposed as answer by Cor Ligthert Friday, May 6, 2011 2:03 PM
- Marked as answer by Kee PoppyModerator Tuesday, May 17, 2011 9:58 AM
Friday, May 6, 2011 1:40 PM -
You say you want to format an array when creating one - I guess that means working in the other direction. If you are always writing out the same set of values to the array then it might be simplest to define a Structure to hold the data. You can then pin the structure in memory, and directly copy the memory into a byte array. If the strings are variable lengths then it probably makes this too tricky.
Otherwise you just have to do it manually. Declare an array large enough to hold the bytes, then use BitConverter and the Encoding class to convert each string and numeric value into a byte array, and write them into the larger array (here's where Buffer.BlockCopy or Array.CopyTo are used).
Module Module1
Sub Main()
Dim bytes = MakeByteArray()
' The message length field starts at index 0:
Dim messageLength As String = BitConverter.ToInt32(bytes, 0)
' The message itself starts at index 4:
Dim message As String = System.Text.ASCIIEncoding.ASCII.GetString(bytes, 4, messageLength)
' The double value starts at index 20:
Dim value As Double = BitConverter.ToDouble(bytes, 20)
' Write the information out to the user:
Console.WriteLine("Message length: " & messageLength)
Console.WriteLine("Message: " & message)
Console.WriteLine("Value: " & value)
End Sub
Private Function MakeByteArray() As Byte()
Dim message As String = "Hello World" & vbCrLf
Dim bytes(27) As Byte
' Read the message length - it's an integer.
' Get the bytes of the integer into an array with GetBytes.
' Copy the bytes of the integer into our target array, called bytes.
Buffer.BlockCopy(BitConverter.GetBytes(message.Length), 0, bytes, 0, 4)
' Similar for the message itself, but we don't need to do the copy as GetBytes can read the
' string into our array.
System.Text.ASCIIEncoding.ASCII.GetBytes(message, 0, message.Length, bytes, 4)
' We don't need to do the padding, the default value of Byte is 0, so the array has 0s at
' those indices.
Dim val As Double = 123456.789
' Copy the 8 bytes of val into the array called bytes writing into it at index 20 onwards.
Buffer.BlockCopy(BitConverter.GetBytes(val), 0, bytes, 20, 8)
Return bytes.ToArray
End Function
End Module
- Marked as answer by Kee PoppyModerator Tuesday, May 17, 2011 9:58 AM
Friday, May 6, 2011 7:58 PM
All replies
-
Bitconverter will get the numeric types.
System.Text.Encoding.ASCII gets you an Encoding object that you can read to use an ASCII string from bytes, you can use the GetString method.
Thursday, May 5, 2011 9:58 PM -
How do i get the first few parts of the array and not the entire array?Friday, May 6, 2011 12:52 PM
-
Array.CopyTo
Creates for you a deep copy from every part you want.
http://msdn.microsoft.com/en-us/library/system.array.copyto(v=VS.100).aspx
Success
CorFriday, May 6, 2011 12:59 PM -
I am trying to read different parts of a byte array and not the entire array. How would I do this? I would also like to format an array when creating one. An example would be the first few parts a string then some integers. Thanks
Another option is Buffer.BlockCopy which allows you to copy the bytes from one array of one type to another array of another type.
Stephen J Whiteley- Proposed as answer by Cor Ligthert Friday, May 6, 2011 2:03 PM
- Marked as answer by Kee PoppyModerator Tuesday, May 17, 2011 9:58 AM
Friday, May 6, 2011 1:40 PM -
Stephen,
That was the one I was looking for, it is a little bit faster.
:-)
Success
CorFriday, May 6, 2011 2:02 PM -
The methods of the BitConverter class all accept a byte array and an integer from which to start reading.
The GetString method of Encoding also accepts an array and an index to start reading from.
Let's say you have recieved a blob of data from some device laid out like this:
Message Length (Integer - Integers are 32 bits, so they use 4 bytes)
Message (String - Each character of an ANSI string uses 1 byte)
Padding (some 0s - Often values are aligned to a 4 byte boundary, so there are padding bytes here so that the next field starts at byte 20)
Value (Double - a 64 bit value so it uses 8 bytes)Here's a sample:
00 0D Message Length
01 00 Message Length
02 00 Message Length
03 00 Message Length
04 48 H
05 65 e
06 6C l
07 6C l
08 6F o
09 20 " "
10 57 W
11 6F o
12 72 r
13 6C l
14 64 d
15 0D Cr
16 0A Lf
17 00 Padding
18 00 Padding
19 00 Padding
20 C9 Value
21 76 Value
22 BE Value
23 9F Value
24 0C Value
25 24 Value
26 FE Value
27 40 ValueYou can use the classes mentioned like this to read the values out:
' The message length field starts at index 0:
Dim messageLength As String = BitConverter.ToInt32(bytes, 0)
' The message itself starts at index 4:
Dim message As String = System.Text.ASCIIEncoding.ASCII.GetString(bytes, 4, messageLength)
' The double value starts at index 20:
Dim value As Double = BitConverter.ToDouble(bytes, 20)
' Write the information out to the user:
Console.WriteLine("Message length: " & messageLength)
Console.WriteLine("Message: " & message)
Console.WriteLine("Value: " & value)
- Marked as answer by Kee PoppyModerator Tuesday, May 17, 2011 9:58 AM
Friday, May 6, 2011 6:55 PM -
You say you want to format an array when creating one - I guess that means working in the other direction. If you are always writing out the same set of values to the array then it might be simplest to define a Structure to hold the data. You can then pin the structure in memory, and directly copy the memory into a byte array. If the strings are variable lengths then it probably makes this too tricky.
Otherwise you just have to do it manually. Declare an array large enough to hold the bytes, then use BitConverter and the Encoding class to convert each string and numeric value into a byte array, and write them into the larger array (here's where Buffer.BlockCopy or Array.CopyTo are used).
Module Module1
Sub Main()
Dim bytes = MakeByteArray()
' The message length field starts at index 0:
Dim messageLength As String = BitConverter.ToInt32(bytes, 0)
' The message itself starts at index 4:
Dim message As String = System.Text.ASCIIEncoding.ASCII.GetString(bytes, 4, messageLength)
' The double value starts at index 20:
Dim value As Double = BitConverter.ToDouble(bytes, 20)
' Write the information out to the user:
Console.WriteLine("Message length: " & messageLength)
Console.WriteLine("Message: " & message)
Console.WriteLine("Value: " & value)
End Sub
Private Function MakeByteArray() As Byte()
Dim message As String = "Hello World" & vbCrLf
Dim bytes(27) As Byte
' Read the message length - it's an integer.
' Get the bytes of the integer into an array with GetBytes.
' Copy the bytes of the integer into our target array, called bytes.
Buffer.BlockCopy(BitConverter.GetBytes(message.Length), 0, bytes, 0, 4)
' Similar for the message itself, but we don't need to do the copy as GetBytes can read the
' string into our array.
System.Text.ASCIIEncoding.ASCII.GetBytes(message, 0, message.Length, bytes, 4)
' We don't need to do the padding, the default value of Byte is 0, so the array has 0s at
' those indices.
Dim val As Double = 123456.789
' Copy the 8 bytes of val into the array called bytes writing into it at index 20 onwards.
Buffer.BlockCopy(BitConverter.GetBytes(val), 0, bytes, 20, 8)
Return bytes.ToArray
End Function
End Module
- Marked as answer by Kee PoppyModerator Tuesday, May 17, 2011 9:58 AM
Friday, May 6, 2011 7:58 PM