You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中不使用BinaryFormatter反序列化其序列化的数据

不用BinaryFormatter反序列化BinaryFormatter序列化数据的方法

方法一:手动解析二进制流

BinaryFormatter的序列化输出有固定结构,核心包含魔法头、类型元数据、实际字段值三部分。针对已知结构的目标类型,可按规则逐字节解析:

  1. 验证并跳过魔法头
    BinaryFormatter开头是固定字节序列:0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,读取并跳过这17字节即可。

  2. 匹配字段顺序解析值
    提前确认原类型的字段名称、类型和顺序,按BinaryFormatter的序列化规则读取对应字节并转换:

    • 值类型(int、bool、DateTime等):直接读取对应字节长度转换
    • 引用类型(string、自定义类等):处理长度标记后读取内容,嵌套类需递归解析

示例代码(针对自定义User类型):

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime CreateTime { get; set; }
}

public static User DeserializeUser(byte[] serializedData)
{
    using var ms = new MemoryStream(serializedData);
    using var reader = new BinaryReader(ms);

    // 跳过魔法头
    reader.ReadBytes(17);
    // 跳过类型元数据(已知结构时可直接跳过,复杂场景需解析元数据匹配字段)

    // 解析Id
    var userId = reader.ReadInt32();
    // 解析Name:先读长度,再读Unicode字节转字符串
    var nameLength = reader.ReadInt32();
    var nameBytes = reader.ReadBytes(nameLength);
    var userName = Encoding.Unicode.GetString(nameBytes);
    // 解析DateTime:读取64位Ticks值转换
    var createTicks = reader.ReadInt64();
    var createTime = new DateTime(createTicks);

    return new User { Id = userId, Name = userName, CreateTime = createTime };
}

手动解析仅适用于结构简单、字段明确的场景,泛型、继承类、循环引用等复杂结构会大幅提升解析难度。

方法二:基于反射实现通用解析

通过反射获取目标类型的字段信息,按BinaryFormatter规则批量读取赋值,适用于字段较多但结构不复杂的类型:

public static T Deserialize<T>(byte[] serializedData) where T : new()
{
    using var ms = new MemoryStream(serializedData);
    using var reader = new BinaryReader(ms);

    // 跳过魔法头
    reader.ReadBytes(17);
    // 跳过类型元数据(需确保目标类型与原类型字段顺序、类型完全匹配)

    var targetObj = new T();
    var fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

    foreach (var field in fields)
    {
        if (field.FieldType == typeof(int))
            field.SetValue(targetObj, reader.ReadInt32());
        else if (field.FieldType == typeof(string))
        {
            var strLen = reader.ReadInt32();
            var strBytes = reader.ReadBytes(strLen);
            field.SetValue(targetObj, Encoding.Unicode.GetString(strBytes));
        }
        else if (field.FieldType == typeof(DateTime))
            field.SetValue(targetObj, new DateTime(reader.ReadInt64()));
        // 可扩展支持更多类型(如bool、long、float等)
    }

    return targetObj;
}

关键注意事项

  • BinaryFormatter格式包含.NET特定类型元数据,跨版本或跨平台可能存在兼容性问题
  • 解析时必须严格遵循BinaryFormatter的序列化规则,包括空值标记、引用重复处理等细节
  • 若原类型涉及继承、泛型或循环引用,手动解析复杂度极高,建议优先获取原类型定义辅助解析

内容的提问来源于stack exchange,提问作者subbaraoc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 17:20:12