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

使用BinaryFormatter序列化反序列化时偶现无效二进制格式错误求助

问题分析与解决方案

你遇到的「输入流不是有效二进制格式」错误,本质是传入GetObject的byte[]并非BinaryFormatter序列化产生的合法数据,可能由以下几种原因导致,对应解决方案如下:

1. 无效的输入字节数组

如果GetBytes序列化失败返回null,而调用方未做判断直接将null或空数组传入GetObject,就会导致反序列化时流内容无效。

修复方案:在GetObject开头添加输入合法性校验:

public static TableData GetObject(byte[] arrBytes)
{
    try
    {
        // 先校验输入是否有效
        if (arrBytes == null || arrBytes.Length == 0)
        {
            Debug.Log("TableDataObject translater: Invalid empty or null byte array");
            return null;
        }
        
        using (var memStream = new MemoryStream())
        {
            var binForm = new BinaryFormatter();
            memStream.Write(arrBytes, 0, arrBytes.Length);
            memStream.Seek(0, SeekOrigin.Begin);
            return (TableData)binForm.Deserialize(memStream);
        }
    }
    catch (Exception ex)
    {
        Debug.Log("TableDataObject translater: "+ ex.Message);
        return null;
    }
}

同时在GetBytes中提前校验输入对象是否为null:

public static byte[] GetBytes(TableData obj)
{
    try
    {
        if (obj == null)
        {
            Debug.Log("Byte maker: Cannot serialize null TableData object");
            return null;
        }
        
        BinaryFormatter bf = new BinaryFormatter();
        using (var ms = new MemoryStream())
        {
            bf.Serialize(ms, obj);
            return ms.ToArray(); // using块会自动释放流,无需手动Close
        }
    }
    catch (Exception ex)
    {
        Debug.Log("Byte maker: "+ ex.Message);
        return null;
    }
}

2. TableData类或嵌套类未标记可序列化特性

BinaryFormatter要求序列化的类及其所有嵌套引用类型成员都必须标记[Serializable]特性,否则序列化过程会生成不完整的字节数组,导致反序列化时格式错误。

修复方案:检查并确保相关类都添加特性:

[Serializable]
public class TableData
{
    // 成员变量如果是自定义类,也要标记[Serializable]
    public NestedData Data;
}

[Serializable]
public class NestedData
{
    // ...
}

3. 数据存储/传输过程中损坏

如果字节数组是从文件、网络或本地存储读取的,可能存在数据截断、编码错误或篡改(比如写入文件时未完成IO操作就中断,网络传输丢包)。

修复方案:

  • 序列化后记录字节数组的长度,反序列化前验证长度是否匹配;
  • 添加简单的校验和(如CRC32)验证数据完整性,示例:
    // 序列化时附加校验和
    public static byte[] GetBytesWithChecksum(TableData obj)
    {
        var rawBytes = GetBytes(obj);
        if (rawBytes == null) return null;
        using (var ms = new MemoryStream())
        {
            ms.Write(rawBytes, 0, rawBytes.Length);
            var crc = BitConverter.GetBytes(Crc32.Compute(rawBytes));
            ms.Write(crc, 0, crc.Length);
            return ms.ToArray();
        }
    }
    
    // 反序列化前校验
    public static TableData GetObjectWithChecksum(byte[] arrBytes)
    {
        if (arrBytes == null || arrBytes.Length < 4) return null;
        var rawLength = arrBytes.Length - 4;
        var rawBytes = new byte[rawLength];
        Array.Copy(arrBytes, 0, rawBytes, 0, rawLength);
        var expectedCrc = BitConverter.ToUInt32(arrBytes, rawLength);
        if (Crc32.Compute(rawBytes) != expectedCrc)
        {
            Debug.Log("TableDataObject translater: Data corrupted");
            return null;
        }
        return GetObject(rawBytes);
    }
    
    (注:Crc32实现可自行封装或使用第三方库)

4. 替换过时的BinaryFormatter(推荐)

BinaryFormatter已被官方标记为过时,存在安全风险(反序列化恶意数据可能导致代码执行),且兼容性差。建议替换为更可靠的序列化库:

示例:使用System.Text.Json

using System.Text.Json;

public static byte[] GetBytes(TableData obj)
{
    try
    {
        if (obj == null) return null;
        return JsonSerializer.SerializeToUtf8Bytes(obj);
    }
    catch (Exception ex)
    {
        Debug.Log("Byte maker: "+ ex.Message);
        return null;
    }
}

public static TableData GetObject(byte[] arrBytes)
{
    try
    {
        if (arrBytes == null || arrBytes.Length == 0) return null;
        return JsonSerializer.Deserialize<TableData>(arrBytes);
    }
    catch (Exception ex)
    {
        Debug.Log("TableDataObject translater: "+ ex.Message);
        return null;
    }
}

示例:使用Protobuf-net(高性能二进制序列化)

先安装NuGet包protobuf-net,然后给类添加特性:

using ProtoBuf;

[ProtoContract]
public class TableData
{
    [ProtoMember(1)]
    public int Id { get; set; }
    [ProtoMember(2)]
    public string Name { get; set; }
}

// 序列化/反序列化方法
public static byte[] GetBytes(TableData obj)
{
    try
    {
        if (obj == null) return null;
        using (var ms = new MemoryStream())
        {
            Serializer.Serialize(ms, obj);
            return ms.ToArray();
        }
    }
    catch (Exception ex)
    {
        Debug.Log("Byte maker: "+ ex.Message);
        return null;
    }
}

public static TableData GetObject(byte[] arrBytes)
{
    try
    {
        if (arrBytes == null || arrBytes.Length == 0) return null;
        using (var ms = new MemoryStream(arrBytes))
        {
            return Serializer.Deserialize<TableData>(ms);
        }
    }
    catch (Exception ex)
    {
        Debug.Log("TableDataObject translater: "+ ex.Message);
        return null;
    }
}

内容的提问来源于stack exchange,提问作者Szendeffy Bálint

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:54:51