0

I recently came across the issue of needing to frequently (& easily) convert & extract bytes from a BigEndian byte array that was being received over TCP. For those unfamiliar with Big/Little Endian, the short version is that each number was sent as MSB then LSB.

When processing and extracting values from the byte array using the default BitConverter on a Little Endian system (read: just about any C#/windows machine), this is a problem.

sirthomas
  • 12,576
  • 1
  • 13
  • 15

2 Answers2

1

Here are some handy extension methods that I created in my project that I thought I would share with fellow readers. The trick here is to only reverse the bytes required for the requested data size.

As a bonus, the byte[ ] extension methods makes the code tidy (in my opinion).

Comments & improvements are welcome.

Syntax to use:

var bytes = new byte[] { 0x01, 0x02, 0x03, 0x04 };
var uint16bigend = bytes.GetUInt16BigE(2);    // MSB-LSB ... 03-04 = 772
var uint16bitconv = bytes.GetUInt16(2);       // LSB-MSB ... 04-03 = 1027   

Here is the class with the initial set of extensions. Easy for readers to extend & customize:

public static class BitConverterExtensions
{
    public static UInt16 GetUInt16BigE(this byte[] bytes, int startIndex)
    {
        return BitConverter.ToUInt16(bytes.Skip(startIndex).Take(2).Reverse().ToArray(), 0);
    }

    public static UInt32 GetUInt32BigE(this byte[] bytes, int startIndex)
    {
        return BitConverter.ToUInt32(bytes.Skip(startIndex).Take(4).Reverse().ToArray(), 0);
    }

    public static Int16 GetInt16BigE(this byte[] bytes, int startIndex)
    {
        return BitConverter.ToInt16(bytes.Skip(startIndex).Take(2).Reverse().ToArray(), 0);
    }

    public static Int32 GetInt32BigE(this byte[] bytes, int startIndex)
    {
        return BitConverter.ToInt32(bytes.Skip(startIndex).Take(4).Reverse().ToArray(), 0);
    }

    public static UInt16 GetUInt16(this byte[] bytes, int startIndex)
    {
        return BitConverter.ToUInt16(bytes, startIndex);
    }

    public static UInt32 GetUInt32(this byte[] bytes, int startIndex)
    {
        return BitConverter.ToUInt32(bytes, startIndex);
    }

    public static Int16 GetInt16(this byte[] bytes, int startIndex)
    {
        return BitConverter.ToInt16(bytes, startIndex);
    }

    public static Int32 GetInt32(this byte[] bytes, int startIndex)
    {
        return BitConverter.ToInt32(bytes, startIndex);
    }
}
sirthomas
  • 12,576
  • 1
  • 13
  • 15
1

You might want to look at using an endian-aware BinaryReader/BinaryWriter implemention. Here are links to some:

Community
  • 1
  • 1
Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
  • Nice links, good to know. Issue with the readers (in my case) is that it implies I know what I'm reading from the stream ahead of time. In my case, I have an array in memory (based on record delimiters + length) that was ingested, then different subclasses will interpret the byte array differently and extract different combinations. The Anculus lib does indeed have a BitConverter that does the trick too. – sirthomas Jun 03 '14 at 01:24