-3
\$\begingroup\$

i get an error after i write player name to the file for second or third time (An unhandled exception of type 'System.InvalidOperationException' occurred in System.Xml.dll

Additional information: There is an error in XML document (18, 17).) (in highscores load method In data = (HighScoreData)serializer.Deserialize(stream); it stops)

the problem is that some how it adds additional ">" at the end of my .dat file could anyone tell me how to fix this?

the file before save looks:

<?xml version="1.0"?>
<HighScoreData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <PlayerName>
    <string>neil</string>
    <string>shawn</string>
    <string>mark</string>
    <string>cindy</string>
    <string>sam</string>
  </PlayerName>
  <Score>
    <int>200</int>
    <int>180</int>
    <int>150</int>
    <int>100</int>
    <int>50</int>
  </Score>
  <Count>5</Count>
</HighScoreData>

the file after save looks:

<?xml version="1.0"?>
<HighScoreData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <PlayerName>
    <string>Nick</string>
    <string>Nick</string>
    <string>neil</string>
    <string>shawn</string>
    <string>mark</string>
  </PlayerName>
  <Score>
    <int>210</int>
    <int>210</int>
    <int>200</int>
    <int>180</int>
    <int>150</int>
  </Score>
  <Count>5</Count>
</HighScoreData>>

the part of my code that does all of save load to xml is: DECLARATIONS PART

  [Serializable]
    public struct HighScoreData
    {
        public string[] PlayerName;
        public int[] Score;

        public int Count;

        public HighScoreData(int count)
        {
            PlayerName = new string[count];
            Score = new int[count];

            Count = count;
        }
    }


    IAsyncResult result = null;
 bool inputName;
    HighScoreData data;
int Score = 0;
    public string NAME;

    public string HighScoresFilename = "highscores.dat";

Game1 constructor

 public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        Width = graphics.PreferredBackBufferWidth = 960;
        Height = graphics.PreferredBackBufferHeight =640;
        GamerServicesComponent GSC = new GamerServicesComponent(this);
        Components.Add(GSC); 
    }

Inicialize function (end of it)

  protected override void Initialize()
    {

//other game code base.Initialize();

        string fullpath =Path.Combine(HighScoresFilename);

        if (!File.Exists(fullpath))
        {
            //If the file doesn't exist, make a fake one...
            // Create the data to save
            data = new HighScoreData(5);
            data.PlayerName[0] = "neil";
            data.Score[0] = 200;

            data.PlayerName[1] = "shawn";
            data.Score[1] = 180;

            data.PlayerName[2] = "mark";
            data.Score[2] = 150;

            data.PlayerName[3] = "cindy";
            data.Score[3] = 100;

            data.PlayerName[4] = "sam";
            data.Score[4] = 50;

            SaveHighScores(data, HighScoresFilename);
        }

}

all methods for loading saving and output

 public static void SaveHighScores(HighScoreData data, string filename)
{
// Get the path of the save game
    string fullpath = Path.Combine("highscores.dat");


// 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(HighScoreData));
serializer.Serialize(stream, data);
}
finally
{
// Close the file
stream.Close();
}
        }


    /* Load highscores */
    public static HighScoreData LoadHighScores(string filename)
    {
    HighScoreData data;

    // Get the path of the save game
    string fullpath = Path.Combine("highscores.dat"); 

    // Open the file
    FileStream stream = File.Open(fullpath, FileMode.OpenOrCreate, FileAccess.Read);
    try
    {
    // Read the data from the file
        XmlSerializer serializer = new XmlSerializer(typeof(HighScoreData));
    data = (HighScoreData)serializer.Deserialize(stream);//this is the line
    // where program gives an error
    }
    finally
    {
    // Close the file
    stream.Close();
    }

    return (data);


    }


    /* Save player highscore when game ends */
    private void SaveHighScore()
    {
    // Create the data to saved
    HighScoreData data = LoadHighScores(HighScoresFilename);

    int scoreIndex = -1;
    for (int i = 0; i < data.Count ; i++)
    {
    if (Score > data.Score[i])
    {
    scoreIndex = i;
    break;
    }
    }

    if (scoreIndex > -1)
    {
    //New high score found ... do swaps
    for (int i = data.Count - 1; i > scoreIndex; i--)
    {
    data.PlayerName[i] = data.PlayerName[i - 1];
    data.Score[i] = data.Score[i - 1];
    }

    data.PlayerName[scoreIndex] = NAME; //Retrieve User Name Here
    data.Score[scoreIndex] = Score; // Retrieve score here

    SaveHighScores(data, HighScoresFilename);
    }
    }

    /* Iterate through data if highscore is called and make the string to be saved*/
    public string makeHighScoreString()
    {
    // Create the data to save
    HighScoreData data2 = LoadHighScores(HighScoresFilename);

    // Create scoreBoardString
    string scoreBoardString = "Highscores:\n\n";


for (int i = 0; i<5;i++)
{
scoreBoardString = scoreBoardString + data2.PlayerName[i] + "-" + data2.Score[i] + "\n";
}
return scoreBoardString;
}

when ill make this work i will start this code when i call game over (now i start it when i press some buttons, so i could test it faster)

   public void InputYourName()
   {
                     if (result == null && !Guide.IsVisible)
                     {

                          string title = "Name";
                          string description = "Write your name in order to save your Score";
                          string defaultText = "Nick";
                          PlayerIndex playerIndex = new PlayerIndex();
                          result= Guide.BeginShowKeyboardInput(playerIndex, title, description, defaultText, null, null);
                        // NAME = result.ToString();

                     }

                if (result != null && result.IsCompleted)
                     {
                         NAME = Guide.EndShowKeyboardInput(result);
                         result = null;
                         inputName = false;
                         SaveHighScore();
                     }

  }

this where i call output to the screen (ill call this in highscores meniu section when i am done with debugging)

spriteBatch.DrawString(Font1, "" + makeHighScoreString(),new Vector2(500,200), Color.White);



  }
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Please have a look at FileMode.OpenOrCreate or FileMode.Create

? Because the former (OpenOrCreate) will have the effect, that if the file already exists, it will simply be opened (without deleting the existing content). Then if the data that you write is shorter than the data that was written before, the additional bytes of the old data will still be part of the new file (at the end). Which will break the XML syntax during loading, as there are additional characters at the end.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .