Data Persistence in C#: A Comprehensive Guide to Serializing Objects to Files

Dec 08, 2025 · Programming · 22 views · 7.8

Keywords: C# | Serialization | File Saving | Binary | XML | JSON

Abstract: This article explores multiple methods for saving object data to files in C#, including binary, XML, and JSON serialization. Through detailed analysis of each technique's implementation principles, use cases, and code examples, it helps developers address data persistence challenges in real-world projects, with practical solutions for complex data structures like game character sheets.

Introduction

Data persistence is a core requirement in software development, especially in game development, desktop applications, and enterprise systems. C# offers various serialization techniques that allow developers to save object states to files and restore them when needed. Based on a real Q&A scenario, this article systematically introduces three mainstream serialization methods—binary, XML, and JSON—analyzes their pros and cons, and provides complete code implementations.

Fundamentals of Serialization

Serialization is the process of converting an object's state into a storable or transmittable format, with deserialization as its reverse. In C#, serialization is used not only for file storage but also in network communication, caching, and configuration management. When choosing a serialization format, factors such as data security, readability, performance, and compatibility must be considered.

Binary Serialization

Binary serialization uses the System.Runtime.Serialization.Formatters.Binary.BinaryFormatter class to convert objects into a compact binary format. This method is efficient and produces small file sizes, but the format is opaque and has strict type requirements.

public static void WriteToBinaryFile<T>(string filePath, T objectToWrite, bool append = false)
{
    using (Stream stream = File.Open(filePath, append ? FileMode.Append : FileMode.Create))
    {
        var binaryFormatter = new BinaryFormatter();
        binaryFormatter.Serialize(stream, objectToWrite);
    }
}

public static T ReadFromBinaryFile<T>(string filePath)
{
    using (Stream stream = File.Open(filePath, FileMode.Open))
    {
        var binaryFormatter = new BinaryFormatter();
        return (T)binaryFormatter.Deserialize(stream);
    }
}

Key requirements: Target types must be marked with the [Serializable] attribute, and fields to ignore use [NonSerialized]. Binary serialization is suitable for storing sensitive data or high-performance scenarios but has poor cross-platform compatibility.

XML Serialization

XML serialization is implemented via System.Xml.Serialization.XmlSerializer, producing human-readable XML files. This method supports cross-platform use and is easy to debug, but files are larger and serialization is slower.

public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
    TextWriter writer = null;
    try
    {
        var serializer = new XmlSerializer(typeof(T));
        writer = new StreamWriter(filePath, append);
        serializer.Serialize(writer, objectToWrite);
    }
    finally
    {
        writer?.Close();
    }
}

public static T ReadFromXmlFile<T>(string filePath) where T : new()
{
    TextReader reader = null;
    try
    {
        var serializer = new XmlSerializer(typeof(T));
        reader = new StreamReader(filePath);
        return (T)serializer.Deserialize(reader);
    }
    finally
    {
        reader?.Close();
    }
}

Notes: Types need a parameterless constructor, only public members are serialized, and [XmlIgnore] is used to exclude properties. XML is ideal for configuration files or data requiring external editing.

JSON Serialization

JSON serialization typically uses the Newtonsoft.Json library (now an alternative to System.Text.Json), generating lightweight JSON files. This method is widely used in modern web development, balancing readability and performance.

public static void WriteToJsonFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
    TextWriter writer = null;
    try
    {
        var contentsToWriteToFile = JsonConvert.SerializeObject(objectToWrite);
        writer = new StreamWriter(filePath, append);
        writer.Write(contentsToWriteToFile);
    }
    finally
    {
        writer?.Close();
    }
}

public static T ReadFromJsonFile<T>(string filePath) where T : new()
{
    TextReader reader = null;
    try
    {
        reader = new StreamReader(filePath);
        var fileContents = reader.ReadToEnd();
        return JsonConvert.DeserializeObject<T>(fileContents);
    }
    finally
    {
        reader?.Close();
    }
}

Requires installing Newtonsoft.Json via NuGet, with [JsonIgnore] to control serialization. JSON is suitable for API interactions and cross-language data exchange.

Application Example: Game Character Sheet Saving

For a Pathfinder character sheet project, define a CharacterSheet class containing character attributes. Choose the serialization method based on needs: binary for high performance and compact storage; XML or JSON for readability and editability.

// Example: Saving and loading a character sheet
WriteToBinaryFile<CharacterSheet>("C:\\CharacterSheet.pfcsheet", characterSheet);
CharacterSheet loadedSheet = ReadFromBinaryFile<CharacterSheet>("C:\\CharacterSheet.pfcsheet");

Extended considerations: When using SaveFileDialog, ensure file paths are valid to avoid "file name is not valid" errors. Incorporate exception handling for robustness.

Technical Comparison and Selection Advice

Binary serialization: Advantages include high performance and small file size; disadvantages are opacity and version sensitivity. XML serialization: Advantages are readability and cross-platform support; disadvantages are large size and slow speed. JSON serialization: Advantages are lightness and universality; disadvantages include dependency on external libraries. For projects like game character sheets, choose binary if for internal use only, or JSON if sharing is required.

Supplementary Method: Text File Writing

For simple data, direct text file writing can be used, as shown in Answer 2. However, this method is unsuitable for complex objects and requires manual parsing.

string lines = "First line.\r\nSecond line.\r\nThird line.";
System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\test.txt");
file.WriteLine(lines);
file.Close();

Suitable for scenarios like logging or simple configurations, but serialization methods offer more systematic solutions.

Conclusion

C# provides flexible serialization options, supporting data persistence from simple text to complex objects. By understanding the principles and implementations of binary, XML, and JSON serialization, developers can effectively address data saving challenges. In real-world projects, evaluate data characteristics, performance requirements, and compatibility needs to select the most appropriate technique. The code examples and best practices in this article can be directly applied to scenarios such as game development and desktop applications, enhancing development efficiency and data management capabilities.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.