【问题标题】:Deserialize - Loading data from a file反序列化 - 从文件加载数据
【发布时间】:2016-01-06 16:53:29
【问题描述】:

我正在使用二进制格式化程序来保存/加载文件中的数据。我有一个图书馆系统,有两个具体的类 - UsersItems - 和一个 abstract 类 - 图书馆。我也在使用两个列表:

List<Item> items = new List<Item>();
List<User> users = new List<User>();


public static void Serialize(object value, string path)
    {
        BinaryFormatter formatter = new BinaryFormatter();

        using (Stream fStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
        {
            formatter.Serialize(fStream, value);
        }
    }

    public static object Deserialize(string path)
    {
        if (!System.IO.File.Exists(path)) { throw new NotImplementedException(); }

        BinaryFormatter formatter = new BinaryFormatter();

        using (Stream fStream = File.OpenRead(path))
        {
            return formatter.Deserialize(fStream);
        }
    }
}

以上是我用来保存和加载的两种方法。

为了从程序文件中调用它们,我使用以下代码进行保存:

string pathItem1 = @"itemList";
string pathUser1 = @"userList";
Library.Serialize(Library.myItems, pathItem1);
Library.Serialize(Library.myUsers, pathUser1);
Console.WriteLine("Serializing...");

这个加载代码:

string pathItem = @"itemList";
string pathUser = @"userList";
//var deserializedItem 
List<Item> items= (List<Item>)Library.Deserialize(pathItem);
//var deserializedUser = 
List<User> users = (List<User>)Library.Deserialize(pathUser);
Console.WriteLine("Deserializing...");

保存似乎工作正常。然而加载不是。我收到此错误消息:

附加信息:无法转换类型为“System.Collections.Generic.List1[LibrarySystem.User]' to type 'System.Collections.Generic.List1[LibrarySystem.Item]”的对象。

谢谢!

【问题讨论】:

    标签: c# serialization deserialization binaryformatter


    【解决方案1】:

    您的Serialize 方法中有一个奇怪的代码。您正在将value 参数保存到两个路径:“itemList”和“userList”。实际上你没有使用路径参数。您的代码应如下所示:

    public static void Serialize(object value, string path)
    {
        BinaryFormatter formatter = new BinaryFormatter();
    
        using (Stream fStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
        {
            formatter.Serialize(fStream, value);
        }
    }
    

    通过此实现,您的代码将按预期工作。

    【讨论】:

    • 代码现在可以正常工作,没有任何错误。但是,在加载时,保存后实际上从文件中加载了任何内容!
    • 这很奇怪,因为我用简单的示例检查了这段代码,而集合(我用 1 和 2 个元素检查了它)实际上是反序列化的。
    • 您可以在调用 Serialize 方法后检查文件是否存在,也可以检查文件内容(如果文件不为空/0 字节就足够了)。然后您可以逐行调试代码以确保您的文件可以在 Deserialize 方法中访问。此外,如果您要保存来自 Library.myUsers 的数据,您可能希望将其加载到同一个变量中吗?然后,使用Library.myUsers = (List&lt;User&gt;)Library.Deserialize(pathUser);
    • 感谢 Vadim Martynov 与 Library.myUsers = (List)Library.Deserialize(pathUser); !真的很感谢它哥们:)!再次感谢!
    【解决方案2】:
    public static void Serialize(object value, string path)
    {
        BinaryFormatter formatter = new BinaryFormatter();
    
        using (Stream fStream = new FileStream(@"itemList", FileMode.Create, FileAccess.Write, FileShare.None))
        {
            formatter.Serialize(fStream, value);
        }
    
        using (Stream fStream = new FileStream(@"userList", FileMode.Create, FileAccess.Write, FileShare.None))
        {
            formatter.Serialize(fStream, value);
        }
    }
    

    您将value 存储在userListitemList 中,尽管将路径作为参数传递。由于最后一次调用是Library.Serialize(Library.myUsers, pathUser1),所以itemList 中的内容是User 对象的列表——这正是错误告诉你的内容。

    修复很明显,只需使用传递的路径,但是您应该考虑使用更健壮的状态存储系统。例如,您可以有一个包含两个列表的类,然后将其序列化。

    跳过一些相对明显的改进(Deserialize 是通用函数的主要候选者,因此您不必每次都强制转换它),一个重要的注意事项是 NotImplementedException 不是什么模糊,您可以根据自己的意思来表达,它在 .Net 框架的上下文中具有非常精确的含义,并且这是您的代码中的一个功能,由于各种原因您没有实现。您想要的“通用”异常是 ArgumentExceptionInvalidOperationException

    【讨论】:

    • 我将代码更改为 @vadim martynov 告诉我的方式。代码现在可以正常工作,没有任何错误。但是,在加载时,保存后实际上从文件中加载了空! - 还将 NotImplementedException 更改为 ArgumentException。
    猜你喜欢
    • 1970-01-01
    • 2017-09-27
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多