Странное поведение XmlSerializer

Поэтому у меня возникли проблемы с десериализацией XML-файла.
Я использую следующую структуру.

[Serializable]
public struct GraphicsOptions
{
    public int Height;
    public int Width;
    public bool Fullscreen;
    public bool AntiAliasing;
    public int ClickResCount;
}

И следующий код для создания,

public void CreateData()
{
    graphicsOptions.Height = graphics.PreferredBackBufferHeight;
    graphicsOptions.Width = graphics.PreferredBackBufferWidth;
    graphicsOptions.Fullscreen = graphics.IsFullScreen;
    graphicsOptions.AntiAliasing = graphics.PreferMultiSampling;
    graphicsOptions.ClickResCount = 1;
    dataStream = File.Create(SavegamePath);
    XmlSerializer serializer = new XmlSerializer(typeof(GraphicsOptions));
    serializer.Serialize(dataStream, graphicsOptions);
    dataStream.Close();
}

Изменить и

private void ApplyChanges()
{
    graphicsOptions.Height = graphics.PreferredBackBufferHeight;
    graphicsOptions.Width = graphics.PreferredBackBufferWidth;
    graphicsOptions.Fullscreen = graphics.IsFullScreen;
    graphicsOptions.AntiAliasing = graphics.PreferMultiSampling;
    graphicsOptions.ClickResCount = clickCountResolution;
    dataStream = File.Open(SavegamePath, FileMode.Open);
    XmlSerializer serializer = new XmlSerializer(typeof(GraphicsOptions));
    serializer.Serialize(dataStream, graphicsOptions);
    dataStream.Close();
}

Загрузите XML-файл

public void LoadData()
{
    dataStream = File.Open(SavegamePath, FileMode.Open);
    XmlSerializer serializer = new XmlSerializer(typeof(GraphicsOptions));
    graphicsOptions = (GraphicsOptions)serializer.Deserialize(dataStream);
    dataStream.Close();
 }

Довольно стандартные вещи, за исключением того, что после третьего применения изменений он решает добавить 2 символа в конец файла: "s>".

Я понятия не имею, почему это происходит, но это делает XML практически бесполезным, потому что я не могу загрузить информацию в свою структуру.
Visual Studio выдает мне InvalidOperationException (я понимаю, почему он это делает).

Любые советы или идеи о том, как предотвратить это или как просто удалить 2 символа, если он поймает исключение?


person Matonster    schedule 21.01.2015    source источник
comment
Было бы очень полезно, если бы вы просто дали нам короткую, но полную программу, демонстрирующую проблему, для которой на самом деле нужно только сохранить файл.   -  person Jon Skeet    schedule 21.01.2015
comment
я дал слишком много информации или недостаточно? рассматриваемая программа сделана с использованием XNA framework, я могу добавить логику обновления, но на самом деле это не даст вам больше информации   -  person Matonster    schedule 21.01.2015
comment
Смесь - слишком много (т.е. какие-то посторонние вещи) и мало (не короткая, а полная программа, демонстрирующая проблему). XNA вероятно не имеет значения, но было бы легко сказать, если бы вы просто создали короткое консольное приложение (не фрагменты, а целую программу), которое показывает проблему.   -  person Jon Skeet    schedule 21.01.2015
comment
Вы пробовали dataStream.Flush() после каждой операции записи?   -  person Pankaj Kapare    schedule 21.01.2015
comment
хороший совет, я пробовал, но не сигары.   -  person Matonster    schedule 21.01.2015


Ответы (2)


Это происходит потому, что ваш новый файл короче, чем раньше. Вы должны использовать FileMode.Create вместо Open/OpenOrCreate

Итак, ваша функция сохранения должна выглядеть так:

private void ApplyChanges()
{
    graphicsOptions.Height = graphics.PreferredBackBufferHeight;
    graphicsOptions.Width = graphics.PreferredBackBufferWidth;
    graphicsOptions.Fullscreen = graphics.IsFullScreen;
    graphicsOptions.AntiAliasing = graphics.PreferMultiSampling;
    graphicsOptions.ClickResCount = clickCountResolution;
    using(dataStream = File.Open(SavegamePath, FileMode.Create))
    {
        XmlSerializer serializer = new XmlSerializer(typeof(GraphicsOptions));
        serializer.Serialize(dataStream, graphicsOptions);
    }
}
person MNie    schedule 21.01.2015
comment
Это не дает мне такой возможности - person Matonster; 21.01.2015
comment
Извините за ошибку, это создать, а не написать: msdn.microsoft.com/en-us/library/ - person MNie; 21.01.2015

Измените метод ApplyChanges(), чтобы использовать другой FileMode, например FileMode.Create. Вы можете найти правильный метод ниже.

 private void ApplyChanges()
 {
    graphicsOptions.Height = graphics.PreferredBackBufferHeight;
    graphicsOptions.Width = graphics.PreferredBackBufferWidth;
    graphicsOptions.Fullscreen = graphics.IsFullScreen;
    graphicsOptions.AntiAliasing = graphics.PreferMultiSampling;
    graphicsOptions.ClickResCount = clickCountResolution;
    dataStream = File.Open(SavegamePath, FileMode.Create); // You can use FileMode.Truncate as well.
    XmlSerializer serializer = new XmlSerializer(typeof(GraphicsOptions));
    serializer.Serialize(dataStream, graphicsOptions);
    dataStream.Close();
  }

См. https://msdn.microsoft.com/en-us/library/system.io.filemode(v=vs.110).aspx

person Lucas Damiani    schedule 21.01.2015