在序列化/反序列化时识别 dataFile 的类型

Posted

技术标签:

【中文标题】在序列化/反序列化时识别 dataFile 的类型【英文标题】:Identify type of dataFile while serializing/deserializing 【发布时间】:2021-09-07 17:24:00 【问题描述】:

我有一个小问题。我想在 c# 中从磁盘内存中反序列化一个文件。一切进展顺利!实际上,它甚至可以工作!除了 id 像我的代码一样健壮,所以我测试如果我加载的数据文件与我要加载的数据不兼容会发生什么。

我要加载的数据是 List 类型的。我试图加载的是一个文本文件,我在其中插入了一些数字并去掉了 .txt 扩展名。但是我遇到了一个例外。

例外:

Test method GuitarWorkshopTests.OrderAdministrationTests.Test_Load_NonAnimal_Class threw exception: 
System.Runtime.Serialization.SerializationException: Het eind van de stroom is bereikt voordat parsering is voltooid.

堆栈跟踪: __BinaryParser.Run() ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) BinaryFormatter.Deserialize(流序列化流) OrderAdministration.Load(字符串文件名)第 119 行 OrderAdministrationTests.Test_Load_NonAnimal_Class() 第 198 行

我摆弄了 fileStream.GetType() 来验证对象的类型是否正确,但我无法使其编译,我错过了一些东西。下面我将展示单元测试及其使用的功能。提前致谢! :D

单元测试:

[TestMethod]
    public void Test_Load_NonAnimal_Class()
    
        InjectorClass injector = new InjectorClass();   

        injector.Administration.Load(@"C:\Users\MyName\Desktop\x");

        Assert.AreEqual(true, injector.Administration.Orders.Count);
    

加载函数:

public void Load(String fileName)
    
        if (fileName == null)
        
            throw new ArgumentNullException("fileName");
        
        String path = @Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\GuitarWorkshop\" + fileName;

        if (fileName.Contains(@"\"))
        
            path = fileName;
        
        else
        
            String direc = @Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\GuitarWorkshop";
            if (!Directory.Exists(direc))
            
                Directory.CreateDirectory(direc);
            
        
        using (FileStream fileStream = File.OpenRead(path))
        
            BinaryFormatter format = new BinaryFormatter();
            if(fileStream.Length > 0)
            
                Orders = format.Deserialize(fileStream) as List<Order>;
            
        
    

【问题讨论】:

二进制格式化程序反序列化仅在使用二进制格式化程序序列化数据时才有效。二进制格式化程序将类型添加到序列化数据中,因此反序列化方法将起作用。 BinaryFormatter 不会正确反序列化损坏的二进制数据。 fileStream.GetType() 与流(文件)类型无关。它是关于 fileStream 实例 .Net 类型,您的示例是 FileStream 【参考方案1】:

这个:

我要加载的数据是 List 类型的。我试图加载的是一个文本文件,我在其中插入了一些数字并去掉了 .txt 扩展名。

还有这个:

BinaryFormatter 格式 = new BinaryFormatter();

不兼容。 BinaryFormatter 写入二进制数据的方式或多或少与数据在内存中的表示方式类似,绝对不是基于文本的,我不建议使用它。

序列化数据有很多不同的方法,可以是基于文本的,也可以是二进制的。它可以遵循定义的通用格式,如 json 或 xml,也可以遵循自定义格式。

如果你只想存储一个数字列表,你可以在每一行放一个数字,用[File.ReadAllLines][2]读取文件并用double.TryParseint.TryParse解析每一行

如果您要序列化对象,我建议使用 Json 之类的格式和 good library 来读取/写入对象。这可能是目前最常用的数据存储方式。

我摆弄了 fileStream.GetType() 来验证对象

这不起作用。 GetType 返回 fileStream 的类型,即FileStream,而不是序列化对象的类型。文件本身需要包含序列化数据的类型。一些序列化格式可以以标准化的方式做到这一点,一些序列化格式在文件前面加上一个对它们的特定文件格式来说是唯一的幻数。

【讨论】:

以上是关于在序列化/反序列化时识别 dataFile 的类型的主要内容,如果未能解决你的问题,请参考以下文章

需要在运行时确定哪些类型 protobuf-net 可以序列化/反序列化

反序列化时如何正确测试数据类型

如何反序列化具有相同名称但不同类型的 API 响应

ServiceStack 文本设置以在反序列化 json 时推断原始值类型

如何在数字反序列化中更改默认类型

当您没有类型时,如何在 .NET 中反序列化 JSON 字符串