Serialization – Saving Objects as Files

Saving and loading a simple Score value

The Basics of saving (in Xml)

Let’s start by saving a simple int variable named Score with xml and binary serialization. Im going to do this inside Unity so that I can save the files to the path defined in Unity’s Application.dataPath. Other than that this can be done completetly without Unity if you supply your own path instead of Application.dataPath.

using System.IO;
using System.Xml.Serialization;
using UnityEngine;

public class SimpleSaving : MonoBehaviour
{
    int Score = 100;

    public void Start()
    {
        using (var stream = new FileStream(Path.Combine(Application.dataPath, "test.xml"), FileMode.Create))
        {
            var formatter = new XmlSerializer(typeof(int));

            formatter.Serialize(stream, Score);
        }
    }
}

The main 3 operations here are filestreams, XmlSerializers and the using notation. To create, open, read from and write to a file we need to establish a connection to that file. That connection is a Filestream, which is located in the System.IO namespace.

using System.IO;
using System.Xml.Serialization;
using UnityEngine;

public class SimpleSaving : MonoBehaviour
{
    int Score = 100;

    public void Start()
    {
        using (var stream = new FileStream(Path.Combine(Application.dataPath, "test.xml"), FileMode.Create))
        {
            var formatter = new XmlSerializer(typeof(int));

            formatter.Serialize(stream, Score);
        }
    }
}

This particular filestream points a file in Application.dataPath that is named test.xml. FileMode.Create means if this file doesn’t already exist an empty file will be created and if it already exists it will be completely overwritten. Regardless of it’s existence or content, writing to this filestream will result in the same file output (and loss of the prior file).
Having established a connection to a file we need to serialize the score variable into a saveable format. To do that we use a Serializer.

using System.IO;
using System.Xml.Serialization;
using UnityEngine;

public class SimpleSaving : MonoBehaviour
{
    int Score = 100;

    public void Start()
    {
        using (var stream = new FileStream(Path.Combine(Application.dataPath, "test.xml"), FileMode.Create))
        {
            var formatter = new XmlSerializer(typeof(int));

            formatter.Serialize(stream, Score);
        }
    }
}

In this cas the serializer we use is a XmlSerializer, which is located in the System.Xml.Serialization namespace. Furthermore we need to specify the type of the data we are going to serialize, in this case an integer, with typeof(int). Having done that we can serialize our Score variable to our file with formatter.Serialize(stream, Score).
After this we should dispose of our filestream, for example with stream.Dispose(), to release it from memory. Alternatively we can use the using(){} notation.

using (var stream = new FileStream(Path.Combine(Application.dataPath, "test.xml"), FileMode.Create))
{
    var formatter = new XmlSerializer(typeof(int));

    formatter.Serialize(stream, Score);
}

Because we declared the filestream inside the using statement c# will automatically dispose it, even if an error occurred.
The test.xml file we receive from this looks like this:

<?xml version="1.0" encoding="Windows-1252"?>
<int>100</int>

We could easily change the score variable from 100 to 100000 by editing it with a text editor.

The Basics of saving (in binary)

Now lets take a look at changes we have to make to save our Score in binary instead.

using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;

public class SimpleSaving : MonoBehaviour
{

    int Score = 100;

    public void Start()
    {
        using (var stream = new FileStream(Path.Combine(Application.dataPath, "test.dat"), FileMode.Create))
        {
            var formatter = new BinaryFormatter();

            formatter.Serialize(stream, Score);
        }
    }
}

Instaed of using a XmlFormatter we use a BinaryFormatter, which is located in the System.Runtime.Serialization.Formatters.Binary namespace. Because a BinaryFormatter can serializes metadata like type infrmation, we don’t have to specifiy the type when we initiaize the formatter. We also change our file extension to .dat to indicate that is is a binary file that is not supposed to be in a human readable format. The test.dat file we receive from this looks like this:

After Serialization = A lot of nonsensical hex code.
Reading and editing this is much harder.

For saving a score this is a much more secure format.