【问题标题】:C# Convert a byte array of an object to list of an objectC#将对象的字节数组转换为对象的列表
【发布时间】:2017-01-27 08:20:31
【问题描述】:

我有一个对象/类,它的成员具有不同的值,都是可序列化的,我可以将一个对象转换为 byte[] 或其他方式。 我正在将这些对象的列表转换为一个大字节数组,如何将其转换回来?

示例对象:

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);
    }
}

并转换为字节数组:

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();

转换回来:

????????

【问题讨论】:

  • 您将不得不将聚合数组拆分为序列化对象大小的块,然后进行反序列化。
  • 由于您没有在项目之间放置任何标记,因此您必须计算单个项目的字节大小,将数据拆分为该大小的块,然后分别处理每个块。
  • 您需要直接序列化对象数组,然后您就可以将整个数组反序列化。 (注意。这是基于切换到 .NET 的整个序列化:不是您自己的东西,但仍将类型标记为使用内置序列化。)

标签: c# arrays converter


【解决方案1】:

如 cmets 中所述,您需要将每个对象的字节写入流中才能反序列化单个对象。示例:

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;
    }
}

您可以在这里看到它的实际效果:https://dotnetfiddle.net/Nk2cks

但 .NET 已经包含一个名为 BinaryFormatter 的序列化程序

Protobuf by google 是另一种可能性。

【讨论】:

  • 为什么让 BinaryWriter 保持打开状态?
  • 如果BinaryWriter关闭MemoryStream之后某些功能无效。但是ToArray() 仍然有效。所以关了也没关系,我的错。
猜你喜欢
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-14
  • 2022-01-18
  • 1970-01-01
相关资源
最近更新 更多