开发者

How to take a collection of bytes and pull typed values out of it?

开发者 https://www.devze.com 2022-12-23 15:15 出处:网络
Say I have a collection of bytes var bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7}; and I want to pull out a defined value from the bytes as a managed type, e.g. a ushort. What is a simple way to def

Say I have a collection of bytes

var bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7};

and I want to pull out a defined value from the bytes as a managed type, e.g. a ushort. What is a simple way to define what types reside at what location in the collection and pull out those values?

One (ugly) way is to use System.BitConverter and a Queue or byte[] with an index and simply iterate through, e.g.:

int index = 0;
ushort first = System.BitConverter.ToUint16(bytes, index);
index += 2; // size of a ushort
int second = System.BitConverter.ToInt32(bytes, index);
index += 4;
...

This method gets very, very tedious when you deal with a lot of these structures!

I know that there is the System.Runtime.InteropServices.StructLayoutAt开发者_开发知识库tribute which allows me to define the locations of types inside a struct or class, but there doesn't seem to be a way to import the collection of bytes into that struct. If I could somehow overlay the struct on the collection of bytes and pull out the values, that would be ideal. E.g.

Foo foo = (Foo)bytes; // doesn't work because I'd need to implement the implicit operator
ushort first = foo.first;
int second = foo.second;
...
[StructLayout(LayoutKind.Explicit, Size=FOO_SIZE)]
public struct Foo  {
    [FieldOffset(0)] public ushort first;
    [FieldOffset(2)] public int second;
}

Any thoughts on how to achieve this?

[EDIT: See also my question on how to deal with the bytes when they are big endian.]


We have done this quite a bit as we talk directly to hardware via bytes over serial.

Given the struct definition

[StructLayout(LayoutKind.Explicit, Size=FOO_SIZE)]
public struct Foo  {
    [FieldOffset(0)] public ushort first;
    [FieldOffset(2)] public int second;
}

You can use a class like this to perform the conversion

public class ByteArrayToStruct<StructType>
{
    public StructType ConvertToStruct(int size, byte[] thebuffer)
    {
        try
        {
            int theSize = size;
            IntPtr ptr1 = Marshal.AllocHGlobal(theSize);
            Marshal.Copy(thebuffer, 0, ptr1, theSize);
            StructType theStruct = (StructType)Marshal.PtrToStructure(ptr1, typeof(StructType));
            Marshal.FreeHGlobal(ptr1);
            return theStruct;
        }
        catch (Exception)
        {
            return default(StructType);
        }
    }
}

Conversely, you could also create List from the array and do something like the following:

ushort first = BitConverter.ToInt16(myList.ToArray(), 0);
myList.RemoveRange(0, sizeof(ushort));
[...]

This would essentially be keeping the relevant data at the "head" of the list, so you wont have to keep track of the position in the array.


do it the first way. define a Buffer class that has the data bytes and a cursor. THen define methods like getInt16, getInt32 etc. Then you go

  Buffer b(bytes);
  ushort a = b.getInt16();
  int x = b.getInt32();

I have this in my utils bag. I also have the opposite, to make a buffer out of ints strings,....

0

精彩评论

暂无评论...
验证码 换一张
取 消