# Why is XmlSerializer adding junk to the end of my file?

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;
}
}


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();
}
}

{
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,
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?

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.