【问题标题】:xml serializing of saved game dataxml序列化保存的游戏数据
【发布时间】:2013-11-29 13:14:22
【问题描述】:

我正在尝试编写一种方法来保存游戏的一些基础数据。目前我正在尝试以 格式保存数据,其父<data> 元素包含<leveldata> 元素数组,其中包含索引、完成和尝试字段。这是我第一次尝试序列化 中的任何内容,所以我遇到了一些问题,目前,当我尝试deserialize 文件时,它正在与invalidoperationexception 一起崩溃(异常的详细信息底部)。

这里是代码。

public void SaveData()
{
    const string filename = "data.vision";

#if WINDOWS_PHONE
    IsolatedStorageFile dataFile = IsolatedStorageFile.GetUserStoreForApplication();
#else
    IsolatedStorageFile dataFile = IsolatedStorageFile.GetUserStoreForDomain();
#endif
    try
    {
        // Create an isolated storage stream and initialize it as null.
        IsolatedStorageFileStream isolatedFileStream = null;

        // Open the isolated storage stream, and write the save data file.
        if (dataFile.FileExists(filename))
        {
            using (isolatedFileStream = dataFile.OpenFile(filename, FileMode.Open,  FileAccess.ReadWrite))
            {
                // Read the data from the file.
                XmlSerializer serializer = new XmlSerializer(typeof(Data));
                // Store each of the deserialized data objects in the list.
                Data savedData = (Data)serializer.Deserialize(isolatedFileStream);


                // Loop through the saved data objects.
                for(int i = 0; i < savedData.Levels.Count; i++)
                {
                    // Get the data object in question.
                    LevelData levelData = savedData.Levels[i];

                    // Check to see if the index of the data object corresponds to the active level index.
                    if (levelData.Index == mLevelIndex)
                    {
                        // Check that the attempts already saved is less.
                        if (levelData.Attempts < mLevel.AttemptCounter)
                            levelData.Attempts = mLevel.AttemptCounter;

                        // Check that the 
                        if (levelData.PercentComplete < 50)
                            levelData.PercentComplete = 50;
                    }
                }
                serializer.Serialize(isolatedFileStream, savedData);
            }  
        }
        else
        {
            // If there is no data file, create a new one.
            using (isolatedFileStream = dataFile.CreateFile(filename))
            {
                // Check the file stream has been initialized.
                if (isolatedFileStream != null)
                {
                    // Create a new data object to store the meta data for the current level.
                    Data data = new Data();
                    // Create a list to store the data already saved.
                    data.Levels = new List<LevelData>();

                    // Initialize the new data values.
                    LevelData levelData = new LevelData();
                    levelData.Index = mLevelIndex;
                    levelData.Attempts = mLevel.AttemptCounter;
                    levelData.PercentComplete = 50;

                    // Add the level data.
                    data.Levels.Add(levelData);

                    // Convert the object to XML data and put it in the stream.
                    XmlSerializer serializer = new XmlSerializer(typeof(Data));
                    // Seriaize the data.
                    serializer.Serialize(isolatedFileStream, data);
                }
            }
        }
    }
    finally
    {
        // Dispose the storage file, in order to commit changes.
        dataFile.Dispose();
    }
}

数据:

public struct Data
{
    /// <summary>
    /// The Level data object.
    /// </summary>
    [XmlArray(ElementName = "Levels")]
    public List<LevelData> Levels;
}

关卡数据

public struct LevelData
{
    /// <summary>
    /// The index of the level.
    /// </summary>
    [XmlElement(ElementName = "Index")]
    public int Index;

    /// <summary>
    /// The number of attempts the player has made for a particular level.
    /// </summary>
    [XmlElement(ElementName = "Attempts")]
    public int Attempts;

    /// <summary>
    /// A value describing the furthest the player has ever got within the level.
    /// </summary>
    [XmlElement(ElementName = "PercentComplete")]
    public int PercentComplete;
}

异常详情:

{System.InvalidOperationException: There is an error in XML document (10, 10). ---> System.Xml.XmlException: Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it. Line 10, position 10.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
   at System.Xml.XmlTextReaderImpl.ParsePI(BufferBuilder piInDtdStringBuilder)
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.XmlReader.ReadEndElement()
   at System.Xml.Serialization.XmlSerializationReader.ReadEndElement()
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderData.Read3_Data(Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderData.Read4_Data()
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, Object events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream)
   at Vision.GameplayScreen.SaveData()
   at Vision.GameplayScreen.HandleInput(InputState input)
   at Vision.ScreenManager.Update(GameTime gameTime)
   at Microsoft.Xna.Framework.Game.<.cctor>b__19(IUpdateable updateable, GameTime gameTime)
   at Microsoft.Xna.Framework.Game.SortingFilteringCollection`1.ForEachFilteredItem[TUserData](Action`2 action, TUserData userData)
   at Microsoft.Xna.Framework.Game.Update(GameTime gameTime)
   at Vision.Game.Update(GameTime gameTime)
   at Microsoft.Xna.Framework.Game.DoUpdate(GameTime gameTime)
   at Microsoft.Xna.Framework.Game.Tick()
   at MonoGame.Framework.WindowsPhone.SurfaceUpdateHandler.Draw(Device device, DeviceContext context, RenderTargetView renderTargetView)
   at MonoGame.Framework.WindowsPhone.DrawingSurfaceUpdateHandler.DrawingSurfaceContentProvider.GetTexture(Size2F surfaceSize, DrawingSurfaceSynchronizedTexture& synchronizedTexture, RectangleF& textureSubRectangle)
   at SharpDX.Direct3D11.DrawingSurfaceContentProviderShadow.DrawingSurfaceContentProviderVtbl.GetTexture(IntPtr thisPtr, IntPtr surfaceSize, IntPtr synchronizedTexture, IntPtr textureSubRectangle)}

【问题讨论】:

  • 显示你得到的实际异常。
  • 能否请您发布完整的异常数据和/或Data class 的定义

标签: xml c# c# xml serialization xna monogame


【解决方案1】:

在读取文件之后,反序列化之前实现这个:

isolatedFileStream.Position = 0;

【讨论】:

  • 遗憾的是,这并没有解决它 - 调试语句显示该位置当时也已经为 0。
  • 能把创建好的XML文件贴出来吗?
【解决方案2】:

序列化/反序列化的代码很好。问题一定出在您对IsolatedStorageFileStream 的使用上,尤其是您正在重用相同的流进行读取和写入这一事实。我建议将它分成两个功能 - 一个用于保存,一个用于加载。然后您可以调用 Load()、Edit()、Save(),或者如果文件不存在则只调用 Create() 和 Save()。

另外,如前所述,将 Xml 发布在磁盘上会有所帮助。它似乎已被加载、保存过程破坏。

我在 LINQPad 中测试了序列化代码,如下所示:

void Main()
{
    var xml = Save();
    Console.WriteLine(xml);
    var data = Load(xml);
    Console.WriteLine("\r\nLevel count: " + data.Levels.Count.ToString());
}

// Define other methods and classes here
public struct LevelData
{
    /// <summary>
    /// The index of the level.
    /// </summary>
    [XmlElement(ElementName = "Index")]
    public int Index;

    /// <summary>
    /// The number of attempts the player has made for a particular level.
    /// </summary>
    [XmlElement(ElementName = "Attempts")]
    public int Attempts;

    /// <summary>
    /// A value describing the furthest the player has ever got within the level.
    /// </summary>
    [XmlElement(ElementName = "PercentComplete")]
    public int PercentComplete;
}

public struct Data
{
    /// <summary>
    /// The Level data object.
    /// </summary>
    [XmlArray(ElementName = "Levels")]
    public List<LevelData> Levels;
}

public string Save()
{
    Data data = new Data();
    // Create a list to store the data already saved.
    data.Levels = new List<LevelData>();

    // Initialize the new data values.
    LevelData levelData = new LevelData();
    levelData.Index = 1;
    levelData.Attempts = 3;
    levelData.PercentComplete = 50;

    // Add the level data.
    data.Levels.Add(levelData);

    // Convert the object to XML data and put it in the stream.
    XmlSerializer serializer = new XmlSerializer(typeof(Data));
    var sb = new StringBuilder();
    using (var sr = new StringWriter(sb))
    {
        // Seriaize the data.
        serializer.Serialize(sr, data);
    }
    return sb.ToString();
}

public Data Load(string xml)
{
    // Convert the object to XML data and put it in the stream.
    XmlSerializer serializer = new XmlSerializer(typeof(Data));
    using (var sr = new StringReader(xml))
    {
        return (Data)serializer.Deserialize(sr);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多