0
\$\begingroup\$

I'm making a game and I am serializing the save game data. The data is simply a few lists of bools, ints and floats.

But about 50% of the time I get an error when the data tries to save or load that says "There is an error in XML document." The error is always located at the end of the file, even after it has changed size or I have added other variables.

It appears that very last part of the XML data is getting copied twice. The last line of the XML should read:

</LevelStats>

But when an error occurs it often reads

</LevelStats>>

Or

</LevelStats>tats>

Or some other small part of the last line duplicated.

Here is the class I am serializing:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Xna.Framework.Storage;
using System.IO;

namespace Jetpack.Classes
{
    [Serializable]
    public struct LevelStats
    {
        // Player Bests
        public List<float?> fTimeList;
        public List<int?> iScoreList;
        public List<int?> iFuelList;

        // Time
        public List<bool> bBronzeTimeList;
        public List<bool> bSilverTimeList;
        public List<bool> bGoldTimeList;

        // Score
        public List<bool> bBronzeScoreList;
        public List<bool> bSilverScoreList;
        public List<bool> bGoldScoreList;

        // Fuel
        public List<bool> bBronzeFuelList;
        public List<bool> bSilverFuelList;
        public List<bool> bGoldFuelList;

        // Level Complete
        public List<bool> bIsLevelComplete;
    }
}

And here are my methods for saving the loading the data:

region Save & Load Level Stats
    public static void SaveLevelStats(LevelStats levelStats, string filename)
    {
        // Get the path of the save game
        string fullpath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), filename);

        // Open the file, creating it if necessary
        FileStream stream = File.Open(fullpath, FileMode.OpenOrCreate);
        try
        {
            // Convert the object to XML data and put it in the stream
            XmlSerializer serializer = new XmlSerializer(typeof(LevelStats));
            serializer.Serialize(stream, levelStats);
        }
        finally
        {
            // Close the file
            stream.Close();
        }
    }

    public static LevelStats LoadLevelStats(string filename)
    {
        LevelStats levelStats;

        // Get the path of the save game
        string fullpath = System.IO.Path.Combine((Directory.GetCurrentDirectory()), filename);

        // Open the file
        FileStream stream = File.Open(fullpath, FileMode.OpenOrCreate,
        FileAccess.Read);
        try
        {
            // Read the data from the file
            XmlSerializer serializer = new XmlSerializer(typeof(LevelStats));
            levelStats = (LevelStats)serializer.Deserialize(stream);
        }
        finally
        {
            // Close the file
            stream.Close();
        }

        return (levelStats);
    }

    #endregion

Why am I getting the error above?

\$\endgroup\$
4
\$\begingroup\$

You're seeing bits of the previous version of the file. In your SaveLevelStats function, change your call to File.Open from

FileStream stream = File.Open(fullpath, FileMode.OpenOrCreate);

to

FileStream stream = File.Open(fullpath, FileMode.Create);

FileMode.OpenOrCreate does not cause truncation of the opened file. That is, when you open the file and it already exists, the existing data is left intact. The returned stream still points to the beginning of the file, however. So when you happen to write an XML state that is shorter than the previously-saved state, you get bits of the previous file left over.

To solve this, want to use a different version of the FileMode enumeration when you call File.Open: Create, which

Specifies that the operating system should create a new file. If the file already exists, it will be overwritten. This requires FileIOPermissionAccess.Write permission. FileMode.Create is equivalent to requesting that if the file does not exist, use CreateNew; otherwise, use Truncate. If the file already exists but is a hidden file, an UnauthorizedAccessException exception is thrown.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.