Hi all. I've got an
someArray(240) As Byte
which I need to unpack into
Int32
and
Int16
integers. I know before I unpack:
1. that all data in
someArray
are integer values
2. what the startposition of each integer is in
someArray
3. what the length of each integer is:
Int32
or
Int16
Currently I have a function which unpacks in the following way:
Function Unpack(someArray() As Byte) As Integer()
Dim i32(4) As Byte
Dim i16(2) As Byte
Dim icount As Integer = 75
Dim ivalues(icount) As Integer
Array.Copy(someArray,0,i32,0,4)
ivalues(0) = Int32FromByteArray(i32,bigEndian)
Array.Copy(someArray,4,i16,0,2)
ivalues(1) = Int16FromByteArray(i16,bigEndian)
Array.Copy(someArray,6,i32,0,4)
ivalues(2) = Int32FromByteArray(i32,bigEndian)
Return ivalues
End Function
Functions
Int32FromByteArray
and
Int16FromByteArray
are functions which use the
BitConverter
class to convert from byte to integer taking into account that the number has to be re-ordered from
BigEndian
to
LittleEndian
.
Now I realize this is a very 'hard coded' way to unpack but I am able to do this because the positions and lengths of the integers in
someArray
are standardized.
My question: is there a way to unpack the byte array
someArray
directly into the integer array
ivalues
? Something like
ivalues = someArray.SplitToInteger(someMask)
?
Obviously the
SplitToInteger
function should do something more clever that my current
Unpack
function does. And obviously it should speed up the unpacking process.
Answers in C# are welcome too of course. Thanks in advance for your thoughts...
Follow-up 1:
I picked solutions 1, 2 and 4 but thanks for the reactions of everyone. I tested out the code of phil.o (solution 1) and it surely works in C#. I'm working now on the conversion to VB.NET which is not trivial because the bit shift operators work a bit differently for the two languages (for those interested:
.net - Binary Shift Differences between VB.NET and C# - Stack Overflow). I will combine phil.o extensions with the Unpack function from F.Xaver in solution 4 but not use the BitConverter class for reasons of Endianess. I will post my wrap up in VB.NET here once I got the VB bitshi(f)t going. Tnx!!
Follow-up 2:
And here it is in VB.NET. The trick in VB with the bitshift is to cast byte first with
CInt
and
then apply the shift (this was already mentioned in the article referenced above, but I didn't pick it up (late) last night).
The big and little Int32 extensions in VB.NET are (btw the name
someArray
has changed to
traceHeader
):
<Extension()>
Public Function GetInt32BigEndian(traceHeader() As Byte, pos As Integer) As Integer
Dim result As Integer = CInt(traceHeader(pos+0)) << 24 Or _
CInt(traceHeader(pos+1)) << 16 Or _
CInt(traceHeader(pos+2)) << 8 Or _
CInt(traceHeader(pos+3))
Return result
End Function
<Extension()>
Public Function GetInt32LittleEndian(traceHeader() As Byte, pos As Integer) As Integer
Dim result As Integer = CInt(traceHeader(pos+3)) << 24 Or _
CInt(traceHeader(pos+2)) << 16 Or _
CInt(traceHeader(pos+1)) << 8 Or _
CInt(traceHeader(pos))
Return result
End Function
I'm going to post a solution myself which I picked up, using Linq. I wonder what you have to say about that...?
Follow-up 3 and close out:
I have tested the answers processing a 6GB file containing 3,506,820 of byte arrays described above (called
someArray
and
traceHeader
). The results are:
1. for 3,506,820 traceHeaders using my original code: 48.04 seconds
2. for the same using solution 1 (bit shifting): 25.28 seconds
3. for the same using my solution 5 using linq: 185.31 seconds
So, solution 1 is the clear winner. My 'solution 5' with linq is not a solution.
Rgds and thanks