C # Загрузка XML и настройка переменных

#c# #xml #loading

#c# #xml #Загрузка

Вопрос:

Я пытаюсь сделать так, чтобы при запуске программы и нажатии кнопки Сохранить (как в видеоиграх) загружались переменные из файла сохранения. Но когда я пытаюсь загрузить переменные, появляется только окно сообщения («Сохранить загружено!»), и XML не перезаписывает мои переменные. Вот код :

     private void MainWindow_Load(object sender, EventArgs e)
    {
        XmlReader xReader = XmlReader.Create("C:\Save\Save1.xml");
        while (xReader.Read())
        {
            if ((xReader.NodeType == XmlNodeType.Element) amp;amp; (xReader.Name == "Variable"))
            {
                if (xReader.HasAttributes)
                {
                    MessageBox.Show("Loaded a save!");
                    Vars.zombies = (Convert.ToDouble(xReader.GetAttribute("Variable","Zombies")));
                    Vars.infected = (Convert.ToDouble(xReader.GetAttribute("Variable","Infected")));
                    Vars.wolfs = (Convert.ToDouble(xReader.GetAttribute("Varaible","Wolfs")));
                }
            }
        }
  

Это когда программа загружается после сохранения. ^

     private void SaveButton_Click(object sender, EventArgs e)
    {
        XmlTextWriter xWriter = new XmlTextWriter("C:\Save\Save1.xml", Encoding.UTF8);
        xWriter.WriteStartDocument();
        xWriter.Formatting = Formatting.Indented;
        xWriter.WriteStartElement("Variables");

        xWriter.WriteStartElement("Variable");
        xWriter.WriteAttributeString("Zombies",Vars.zombies.ToString());
        xWriter.WriteEndElement();

        xWriter.WriteStartElement("Variable");
        xWriter.WriteAttributeString("Infected",Vars.infected.ToString());
        xWriter.WriteEndElement();

        xWriter.WriteStartElement("Variable");
        xWriter.WriteAttributeString("Wolfs",Vars.wolfs.ToString());

        xWriter.WriteEndElement();
        xWriter.WriteEndElement();
        xWriter.Close();
    }
  

Это код, который сохраняет переменные ^

 public static double infected = 0;
public static double zombies = 0;
public static double wolfs = 0;
  

И, наконец, переменные в отдельном классе ^

Кто-нибудь может сказать мне, что я делаю не так? Сохранение работает идеально, но программа просто не загружает переменные.

Комментарии:

1. Ваши статические настройки инициализированы в 0, а метод Convert возвращает 0, потому что вы переходите к нему, null возвращаемому xReader.GetAttribute . getAttribute принимает пространство имен в качестве второго параметра, поэтому вы используете его неправильно. Я полагаю, вам нужно найти узел //Variables/Variable (уже выполненный с помощью while цикла), а затем получить его атрибуты с помощью node.GetAttribute("Infected") etc. Кстати, у вас есть опечатка «Varaible» в последней строке метода загрузки.

2. Хм, у меня сейчас голова кругом идет кругом, поскольку я уже некоторое время пытаюсь это исправить, не могли бы вы рассказать немного подробнее о том, что мне следует изменить?

3. @elgonzo Convert.ToDouble будет не исключение. «Число с плавающей запятой двойной точности, эквивалентное числу в значении, или 0 (ноль), если значение равно нулю». — согласно MSDN

4. @Tommi, ты прав, ToDouble не выдает ошибку, если передана null ссылка.. Черт возьми, по-видимому, я больше не могу читать документацию MSDN — что со мной случилось? … 🙂

5. почему бы не использовать файл настроек?

Ответ №1:

Вы можете попробовать следующий код для теста.

 Vars.zombies = (Convert.ToDouble(xReader.GetAttribute("Zombies")));
Vars.infected = (Convert.ToDouble(xReader.GetAttribute("Infected")));
Vars.wolfs = (Convert.ToDouble(xReader.GetAttribute("Wolfs")));
  

Внутри GetAttributes вам просто нужно передать имя атрибута, значение которого вы пытаетесь получить. Второй необязательный параметр принимает URI пространства имен атрибута.

Ответ №2:

Я покажу вам очень наивный подход, который подходит для нескольких переменных. Пожалуйста, подумайте о том, чтобы использовать какую-нибудь мощную функцию, например DataContractSerializer , если вам нужно сохранить больше данных.

Прежде всего, я бы начал переходить от атрибутов к значениям, ваша текущая реализация требует более сложного поиска в файле XML.

  private static void Save()
    {
        var xWriter = new XmlTextWriter("Save1.xml", Encoding.UTF8);
        xWriter.WriteStartDocument();
        xWriter.Formatting = Formatting.Indented;
        xWriter.WriteStartElement("Variables");

            xWriter.WriteStartElement("Zombies");
            xWriter.WriteValue(Vars.zombies);
            xWriter.WriteEndElement();

            xWriter.WriteStartElement("Infected");
            xWriter.WriteValue(Vars.infected);
            xWriter.WriteEndElement();

            xWriter.WriteStartElement("Wolfs");
            xWriter.WriteValue(Vars.wolfs);
            xWriter.WriteEndElement();

        xWriter.WriteEndElement();
        xWriter.Close();
    }
  

Здесь я использовал writeValue вместо WriteAttributeString . Это дает нам xml, подобный

 <?xml version="1.0" encoding="utf-8"?>
<Variables>
  <Zombies>1</Zombies>
  <Infected>1</Infected>
  <Wolfs>1</Wolfs>
</Variables>
  

Теперь мы используем прямое считывание значений для получения данных:

 private static void Read()
        {
            XmlReader xReader = XmlReader.Create("Save1.xml");
            while (xReader.Read())
            {
                if (xReader.NodeType == XmlNodeType.Element)
                {
                    switch (xReader.Name)
                    {
                        case "Zombies":
                            Vars.zombies = xReader.ReadElementContentAsDouble();
                        break;
                        case "Infected":
                            Vars.infected = xReader.ReadElementContentAsDouble();
                        break;
                        case "Wolfs":
                            Vars.wolfs = xReader.ReadElementContentAsDouble();
                        break;
                    }
                }
            }
        }
  

Вот полная демонстрация:https://dotnetfiddle.net/0rQUsD