简体   繁体   中英

Convert a List of objects to a byte array in c#

I have this struct definition:

public struct ChangedByte
{
    public byte R;
    public byte G;
    public byte B;
    public int x;
    public int y;
}

I have created a:

List<ChangedByte> testme = new List<ChangedByte>();

(and added items to it)

I convert this to an Array:

ChangedByte[] alpha = testme.ToArray();

I have this function I found with a similar question on SO:

byte[] StructureToByteArray(object obj)
{
    int len = Marshal.SizeOf(obj);
    byte[] arr = new byte[len];
    IntPtr ptr = Marshal.AllocHGlobal(len);
    Marshal.StructureToPtr(obj, ptr, true);
    Marshal.Copy(ptr, arr, 0, len);
    Marshal.FreeHGlobal(ptr);
    return arr;
}

I call it like this:

byte[] test = StructureToByteArray(alpha);

I get the error:

Type 'new_encoder.Form1+ChangedByte[]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

I would like to convert a list of objects into a byte array (and possibly avoid serialization as it tends to bulk up the size of the array)

Can it be done?

ADDITIONAL:

I have tried amending the Struct to this:

public struct ChangedByte
{
    [MarshalAs(UnmanagedType.LPWStr)]
    public byte R;
    [MarshalAs(UnmanagedType.LPWStr)]
    public byte G;
    [MarshalAs(UnmanagedType.LPWStr)]
    public byte B;
    [MarshalAs(UnmanagedType.LPWStr)]
    public int x;
    [MarshalAs(UnmanagedType.LPWStr)]
    public int y;
}

but still the same error.

You can use the following methods:

static byte[] ArrayToBytes<T>(T[] array) where T : struct
{
    IntPtr ptr = IntPtr.Zero;
    try
    {
        int len = Marshal.SizeOf(typeof(T));
        int totalLen = array.Length * len;
        ptr = Marshal.AllocHGlobal(len);
        for (int i = 0; i < array.Length; i++)
        {
            Marshal.StructureToPtr(array[i], ptr + i * len, false);
        }
        var bytes = new byte[totalLen];
        Marshal.Copy(ptr, bytes, 0, totalLen);
        return bytes;
    }
    finally
    {
        if (ptr != IntPtr.Zero)
            Marshal.FreeHGlobal(ptr);
    }
}

static T[] ArrayFromBytes<T>(byte[] bytes) where T : struct
{
    IntPtr ptr = IntPtr.Zero;
    try
    {
        int len = Marshal.SizeOf(typeof(T));
        int count = bytes.Length / len;
        ptr = Marshal.AllocHGlobal(bytes.Length);
        Marshal.Copy(bytes, 0, ptr, bytes.Length);
        T[] array = new T[count];
        for (int i = 0; i < count; i++)
        {
            array[i] = Marshal.PtrToStructure<T>(ptr + i * len);
        }
        return array;
    }
    finally
    {
        if (ptr != IntPtr.Zero)
            Marshal.FreeHGlobal(ptr);
    }
}

And use them like this:

byte[] test = ArrayToBytes(alpha); // serialize
ChangedByte[] alpha2 = ArrayFromBytes<ChangedByte>(test); // deserialize

In this case since you aren't only converting a struct, but an array of structs, you will need to loop through your array and convert each item. Use pointer arithmetic to move through your buffer and add the items.

public static byte[] StructureArrayToByteArray(ChangedByte[] objs)
{
    int structSize = Marshal.SizeOf(typeof(ChangedByte));
    int len = objs.Length * structSize;
    byte[] arr = new byte[len];
    IntPtr ptr = Marshal.AllocHGlobal(len);
    for (int i = 0; i < objs.Length; i++ ) {
        Marshal.StructureToPtr(objs[i], ptr + i*structSize, true);
    }
    Marshal.Copy(ptr, arr, 0, len);
    Marshal.FreeHGlobal(ptr);
    return arr;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM