Iceflower S
Iceflower S

Reputation: 194

C# Convert a byte array of an object to list of an object

I have an object/ class with different values as members, all serializable, i can convert one object to an byte[] and other way around. I was converting a list of those objects into one big byte array, how can i convert it back?

Example object:

using System;
using System.IO;

[Serializable]
public class MyItem {
    internal string m_name = "";
    internal int m_position = 0;
    internal float m_color = 0f;
    internal int m_direction = 0;
    internal float m_power = 0f;

    public MyItem(string name, int position, float color, int direction, float power) {
        m_name = name;
        m_position = position;
        m_color = color;
        m_direction = direction;
        m_power = power;
    }

    public byte[] Serialize() {
        using (MemoryStream m = new MemoryStream()) {
            using (BinaryWriter writer = new BinaryWriter(m)) {
                writer.Write(m_name);
                writer.Write(m_position);
                writer.Write(m_color);
                writer.Write(m_direction);
                writer.Write(m_power);
            }
            return m.ToArray();
        }
    }

    public static MyItem Desserialize(byte[] data) {
        string name;
        int position;
        float color;
        int direction;
        float power;

        using (MemoryStream m = new MemoryStream(data)) {
            using (BinaryReader reader = new BinaryReader(m)) {
                name = reader.ReadString();
                position = reader.ReadInt32();
                color = reader.ReadSingle();
                direction = reader.ReadInt32();
                power = reader.ReadSingle();
            }
        }

        return new MyItem(name, position, color, direction, power);
    }
}

And converting to byte array:

List<MyItem> itemlist = <...>;
List<byte[]> byteList = new List<byte[]>();
for (int i = 0; i < itemlist.Count; i++) {
    byteList.Add(itemlist[i].Serialize());
}
byte[] data = byteList.SelectMany(bytes => bytes).ToArray();

Converting back:

????????

Upvotes: 0

Views: 8244

Answers (1)

Nico
Nico

Reputation: 3542

As stated in the comments, you need to write the bytes of each object in the stream to be able to deserialize a single object. Example:

public static class MyItemSerializer
{
    public static byte[] Serialize(this IEnumerable<MyItem> items)
    {
        using (MemoryStream m = new MemoryStream()) 
        {
            using (BinaryWriter writer = new BinaryWriter(m, System.Text.Encoding.UTF8, true)) 
            {
                foreach (var item in items) 
                {
                    var itemBytes = item.Serialize();
                    writer.Write(itemBytes.Length);
                    writer.Write(itemBytes);
                }

            }

            return m.ToArray();
        }
    }

    public static List<MyItem> Deserialize(byte[] data)
    {
        var ret = new List<MyItem>();
        using (MemoryStream m = new MemoryStream(data))
        {
            using (BinaryReader reader = new BinaryReader(m, System.Text.Encoding.UTF8)) 
            {
                while (m.Position < m.Length)
                {
                    var itemLength = reader.ReadInt32();
                    var itemBytes = reader.ReadBytes(itemLength);
                    var item = MyItem.Desserialize(itemBytes);
                    ret.Add(item);
                }
            }
        }

        return ret;
    }
}

Here you can see it in action: https://dotnetfiddle.net/Nk2cks

But .NET already contains a serializer called BinaryFormatter

Protobuf by google is another possibility.

Upvotes: 1

Related Questions