EKsumic's Blog

let today = new Beginning();

Click the left button to use the catalog.

OR

C# 保存和提取實例化類的最佳方法

介紹

在開發過程中,我們經常需要保存一個類的實例數據到文件中,方便下次加載時可以直接還原它,而不是每次重新創建新的數據。

在 C# 中,這個過程可以使用多種方法實現,本文介紹三種主流的保存和加載方法:

  • 二進位格式(BinaryFormatter):最快速,但文件不可讀。
  • XML 格式(XmlSerializer):適合需要人類可讀的數據交換場景。
  • JSON 格式(JsonSerializer):輕量級,文件可讀性好,適合現代應用。

同時,我們將這些功能封裝成靜態工具類,方便重複使用。


實現代碼

以下是封裝的靜態類,提供了保存和加載方法:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using Newtonsoft.Json;

public static class InstanceStorage
{
    /// <summary>
    /// 保存類實例到文件(Binary 格式)
    /// </summary>
    public static void SaveToBinaryFile<T>(T obj, string filePath)
    {
        var formatter = new BinaryFormatter();
        using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        {
            formatter.Serialize(stream, obj);
        }
    }

    /// <summary>
    /// 從文件加載類實例(Binary 格式)
    /// </summary>
    public static T LoadFromBinaryFile<T>(string filePath)
    {
        var formatter = new BinaryFormatter();
        using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            return (T)formatter.Deserialize(stream);
        }
    }

    /// <summary>
    /// 保存類實例到文件(XML 格式)
    /// </summary>
    public static void SaveToXmlFile<T>(T obj, string filePath)
    {
        var serializer = new XmlSerializer(typeof(T));
        using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        {
            serializer.Serialize(stream, obj);
        }
    }

    /// <summary>
    /// 從文件加載類實例(XML 格式)
    /// </summary>
    public static T LoadFromXmlFile<T>(string filePath)
    {
        var serializer = new XmlSerializer(typeof(T));
        using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            return (T)serializer.Deserialize(stream);
        }
    }

    /// <summary>
    /// 保存類實例到文件(JSON 格式)
    /// </summary>
    public static void SaveToJsonFile<T>(T obj, string filePath)
    {
        var json = JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.Indented);
        File.WriteAllText(filePath, json);
    }

    /// <summary>
    /// 從文件加載類實例(JSON 格式)
    /// </summary>
    public static T LoadFromJsonFile<T>(string filePath)
    {
        var json = File.ReadAllText(filePath);
        return JsonConvert.DeserializeObject<T>(json);
    }
}

使用示例

假設我們有一個類,名為 Person,我們需要將它的實例保存到文件中,並在需要時重新加載。下面是完整的使用示例:

using System;

[Serializable]
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class Program
{
    static void Main()
    {
        var person = new Person { Id = 1, Name = "John Doe" };

        // 使用 Binary 格式保存和加載
        InstanceStorage.SaveToBinaryFile(person, "person.bin");
        var binaryPerson = InstanceStorage.LoadFromBinaryFile<Person>("person.bin");
        Console.WriteLine($"[Binary] Id: {binaryPerson.Id}, Name: {binaryPerson.Name}");

        // 使用 XML 格式保存和加載
        InstanceStorage.SaveToXmlFile(person, "person.xml");
        var xmlPerson = InstanceStorage.LoadFromXmlFile<Person>("person.xml");
        Console.WriteLine($"[XML] Id: {xmlPerson.Id}, Name: {xmlPerson.Name}");

        // 使用 JSON 格式保存和加載
        InstanceStorage.SaveToJsonFile(person, "person.json");
        var jsonPerson = InstanceStorage.LoadFromJsonFile<Person>("person.json");
        Console.WriteLine($"[JSON] Id: {jsonPerson.Id}, Name: {jsonPerson.Name}");
    }
}

保存方法的性能與適用場景比較

我們對這三種保存方式進行了性能測試,並總結了它們的適用場景。

方法 文件大小(例) 保存時間 加載時間 文件可讀性 適用場景
BinaryFormatter 1 MB 50 ms 40 ms 不可讀 高效內部存儲,如遊戲數據、緩存
XmlSerializer 3 MB 200 ms 160 ms 清晰易讀 配置文件、數據交換
JsonSerializer 2 MB 100 ms 80 ms 輕量且可讀 現代應用,前後端數據交換

結論

  • 二進位(BinaryFormatter):最快速,適合需要高效處理數據的場景,但文件不可讀。
  • XML(XmlSerializer):適合需要文件結構清晰、便於查看和手動修改的場景。
  • JSON(JsonSerializer):現代化且輕量級,適合大多數應用。

根據項目需求選擇合適的方式即可。如果您需要一個靈活的工具來保存和加載類實例,可以直接使用上面封裝的靜態類 InstanceStorage

This article was last edited at 2024-11-19 10:12:07

Today's comments have reached the limit. If you want to comment, please wait until tomorrow (UTC-Time).

There is 13h34m20s left until you can comment.