System.InvalidCastException异常求助:二进制文件读取类型转换无效
解决BinaryFormatter反序列化时的InvalidCastException问题
咱们先来拆解下你碰到的System.InvalidCastException最可能的几个原因,再逐个对应给出解决思路:
1. 序列化/反序列化的GameSaved结构体定义不匹配
BinaryFormatter对类型的匹配要求极其严格——当初序列化这个二进制文件时的GameSaved结构体,必须和你现在用来反序列化的版本完全一致,差一点都不行:
- 字段的名称、数据类型必须丝毫不差
- 字段的声明顺序不能改动
- 不能新增或删除字段
- 结构体的命名空间、访问修饰符(比如必须是
public)也要和之前一致 - 如果结构体里嵌套了其他自定义类型,那些类型也得满足同样的匹配要求
检查建议:翻出当初生成这个二进制文件的代码,对比当前的GameSaved结构体,把所有不一致的地方修正过来。
2. 二进制文件不是用BinaryFormatter序列化的
如果这个文件是用其他方式生成的(比如手动写的二进制数据、Json转二进制、或者Protobuf等其他序列化工具),那用BinaryFormatter反序列化肯定会失败——因为它只认自己的序列化格式。
验证方法:
- 用十六进制编辑器打开文件,BinaryFormatter生成的文件开头通常有固定的魔术数字(比如
0x00010000) - 用你当初序列化的代码重新生成一个测试文件,对比两个文件的头部和整体结构,看是否一致
3. 流操作或类型转换代码有问题
看你贴的代码,最后只写到GameSaved newdata...,推测你可能是直接强制转换了反序列化的结果,比如:
GameSaved newdata = (GameSaved)formatter.Deserialize(mStream);
如果反序列化出来的对象根本不是GameSaved类型,就会抛出转换异常。
修正建议:
- 先把反序列化结果存为
object,再做类型检查:var deserializedObj = formatter.Deserialize(mStream); if (deserializedObj is GameSaved newdata) { // 这里处理你的newdata } else { throw new InvalidOperationException("反序列化得到的对象不是GameSaved类型"); } - 另外,你的流操作可以简化,不需要先把文件读到byte[]再转MemoryStream,直接用FileStream反序列化更高效:
using (FileStream fs = new FileStream(filename1, FileMode.Open, FileAccess.Read)) { BinaryFormatter formatter = new BinaryFormatter(); var deserializedObj = formatter.Deserialize(fs); if (deserializedObj is GameSaved newdata) { // 处理逻辑 } }
4. 结构体缺少[Serializable]特性
BinaryFormatter只能序列化/反序列化标记了[Serializable]特性的类型,如果你忘了给GameSaved加这个特性,也会导致异常(有时候会直接抛出SerializationException,但也可能间接引发转换问题)。
修正代码:
[Serializable] public struct GameSaved { // 你的字段定义 }
额外提醒:BinaryFormatter已过时
微软已经把BinaryFormatter标记为过时(Obsolete)了,因为它存在严重的安全风险——反序列化不可信数据可能导致远程代码执行。如果你的项目是新开发的,建议换成更安全的序列化方式,比如:
System.Text.Json(适合大多数场景)Newtonsoft.Json(兼容性更好)- Protobuf(适合高性能、跨平台场景)
内容的提问来源于stack exchange,提问作者England Germany
相关产品推荐
相关产品推荐

