Unity学习日记(十三) xml文件简单的操作(一)

本文详细介绍了如何在Unity中创建、保存、读取XML文件,并通过改进代码提高效率及灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在游戏中Xml文件是经常会用来存储游戏信息或者是存储游戏数据,那么我们就需要对其Xml文件进行创建、保存、读取、删除等操作。这里简单介绍在Unity下怎样多Xml文件进行操作。

  Xml文件的操作是.net标准模板库里面的基本功能,因此需要引入这个模板库才能进行操作,如下所示:

  

  代码如下所示:

 public static void CreateXml(string path)
 {
        XmlDocument xmlDoc = new XmlDocument();
        ////创建类型声明节点    
        try
        {
                xmlDoc.Save(path);
        }
            catch (Exception e)
            {
                //显示错误信息    
                Debug.Log(e.Message);
            }
        }
 }

   这里只需要传入你想将数据保存到的path路径位置即可,这样你就可以创建一个简单到Xml文件即可,但是这样创建有个xml有个问题,如果文件夹中有个文件就会报错。

   那么为了避免这个问题要怎么修改代码呢?

  这里我就需要引入另一个标准模板库,进行文件查找和检查重复的问题。如下所示:

  代码如下所示:

 public static void CreateXml(string path)
 {
        XmlDocument xmlDoc = new XmlDocument();
        ///检查文件是否存在
        if (File.Exists(path))
        {
            Console.WriteLine("该文件已存在!!");
            Debug.Log("该文件已存在!!");
            return;
        }
        else //不存在就创建
        {
            try
            {
                xmlDoc.Save(path);
            }
            catch (Exception e)
            {
                //显示错误信息    
                Debug.Log(e.Message);
            }
        }
  }
  这样就可以避免了出现问题了,提高了代码的健壮性。然后测试下代码,如下所示:


这里我就简单的用UI去测试在文件夹下创建一个test3.xml文件,测试结果如下所示:

 打开test3.xml文件会发现这个文件是空的并没有任何的数据在里面,这样不利于区别这个文件究竟有没有使用过或者是使用情况,我希望创建的时候xml文件就具有简单的数据格式。那么需要再次改写代码,代码如下

public static void CreateXml(string path, StringBuilder data = null)
    {
        XmlDocument xmlDoc = new XmlDocument();
        ////创建类型声明节点    
        XmlNode node = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "");
        xmlDoc.AppendChild(node);
        //创建根节点    
        XmlNode root = xmlDoc.CreateElement("User");
        xmlDoc.AppendChild(root);
        CreateNode(xmlDoc, root, "path", "xuwei");
        CreateNode(xmlDoc, root, "sex", "male");
        CreateNode(xmlDoc, root, "age", "25");

        ///检查文件是否存在
        if (File.Exists(path))
        {
            Console.WriteLine("该文件已存在!!");
            Debug.Log("该文件已存在!!");
            return;
        }
        else //不存在就创建
        {
            try
            {
                xmlDoc.Save(path);
            }
            catch (Exception e)
            {
                //显示错误信息    
                Debug.Log(e.Message);
            }
        }
    }
添加节点的代码:

 private static void CreateNode(XmlDocument xmlDoc, XmlNode parentNode, string name, string value)
    {
        XmlNode node = xmlDoc.CreateNode(XmlNodeType.Element, name, null);
        node.InnerText = value;
        parentNode.AppendChild(node);
    }

代码已经写好了来测试一下功能,这次我把数据信息存放到test4.xml文件里面查看,测试效果如下所示:


如果使用一段时间会觉得这样的函数非常繁琐,如果数据结构不一样就需要改写这个函数这样非常麻烦的做法,有没有比较方便的方式。根据这个需求继续修改这个函数,我们在往这个类添加一个标准模板库,如下所示:


然后将代码改写成最后的效果,代码如下:

/// <summary>
    /// 创建一个空的xml文件
    /// </summary>
    /// <param path="path">xml文件名</param>
    /// <param StringBuilder="data">添加数据</param>
    public static void CreateXml(string path, StringBuilder data = null)
    {
        XmlDocument xmlDoc = new XmlDocument();
        ////创建类型声明节点    
        XmlNode node = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "");
        ///检查文件是否存在
        if (File.Exists(path))
        {
            Console.WriteLine("该文件已存在!!");
            Debug.Log("该文件已存在!!");
            return;
        }
        else //不存在就创建
        {
            try
            {
                xmlDoc.Save(path);
                if (data != null)
                {
                    string t = data.ToString();
                    StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8);
                    sw.Write(t);
                    sw.Flush();
                    sw.Dispose();
                }
            }
            catch (Exception e)
            {
                //显示错误信息    
                Debug.Log(e.Message);
            }
        }
    }
最后的测试代码如下:

public void OnClickCreateButton()
    {
        string path = String.Format(Consts.DataTestDir + "{0}.xml", "test");
        Tools.CreateXml(path, CreateWriteXml("Begonia", "22324", "1890685", "25"));
        
    }
测试效果效果如下所示:


创建了xml文件并不是最后的效果,我们还要进行数据的保存这个数据,保存数据的代码比较简单,我直接将用注释来解释即可,代码如下:

/// <summary>
    /// 保存数据文件
    /// </summary>
    /// <param name="fileName">文件路径</param>
    /// <param name="sb">保存的数据排版</param>
    public static void SaveXml(string fileName, StringBuilder sb)
    {
        //检查文件是否存在
        if(!File.Exists(fileName))
            return;
        //数据转化为字符串
        string t = sb.ToString();
        //找到xml文件
        StreamWriter sw = new StreamWriter(fileName, false, Encoding.UTF8);
        sw.Write(t);//写入数据
        //保存并且关闭xml文件
        sw.Flush();
        sw.Dispose();
    }
那么最后是数据操作的介绍了,读取数据方法,方法代码如下:

private void LoadXml(string fileName, ref Player player)
    {
        //获取xml路径下的文件
        FileInfo file = new FileInfo(fileName);
        StreamReader sr = new StreamReader(file.OpenRead(), Encoding.UTF8);

        //打开并且读取xml文件
        XmlDocument doc = new XmlDocument();
        doc.Load(sr);

        player.Name = doc.SelectSingleNode("/Level/Name").InnerText;
        player.QQ = int.Parse(doc.SelectSingleNode("/Level/QQ").InnerText);
        player.Phone = doc.SelectSingleNode("/Level/Phone").InnerText;
        player.Year = int.Parse(doc.SelectSingleNode("/Level/Year").InnerText);
        //关闭xml文件并且释放资源
        sr.Close();
        sr.Dispose();
    }
这样不难发现,因为xml数据格式都是自定义的,所以会有很多层级关系,这样一来我们就要写很多个LoadXml方法如此一来。除去数据以外其他的代码都是一样的,这样我们可与不可以将其抽取出来单独形成一个函数方法呢?答案是可以的。

实现这个函数需要用到委托进行(PS:不懂委托方法的小朋友自行谷歌度娘),每次调用函数的时候就需要提供数据提取方法。最后实现的代码如下所示:

 /// <summary>
    /// 读取xml的数据
    /// </summary>
    /// <typeparam name="T">泛型</typeparam>
    /// <param name="fileName">xml的路径</param>
    /// <param name="rm">读取的数据的方法</param>
    /// <param name="data">读取数据</param>
    public static void LoadDataFromXml<T>(string fileName, ReadMethod<T> rm, ref T data)
    {
        //查找xml文件是否存在
        if(!File.Exists(fileName))
            return;
        //获取xml路径下的文件
        FileInfo file = new FileInfo(fileName);
        StreamReader sr = new StreamReader(file.OpenRead(), Encoding.UTF8);
        //委托方法
        rm(sr, ref data);
        //关闭xml文件并且释放资源
        sr.Close();
        sr.Dispose();
    }
这里使用泛型和委托两种方式共同实现了读取数据这块的功能。然后进行简单测试,测试代码如下:


最后在Unity下测试的效果如下图所示:


最后将这个方法统一放到Tools工具类函数里面进行统一管理,代码如下所示:

using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Xml;

public static class Tools
{
    public delegate void ReadMethod<T>(StreamReader sr, ref T type);
    /// <summary>
    /// 获取Path目录下的所有文件
    /// </summary>
    /// <param path="path"></param>
    /// <param path="type"></param>
    /// <returns></returns>
    public static List<FileInfo> GetAllFile(string path, string type)
    {
        string[] files = Directory.GetFiles(path, type);
        List<FileInfo> list = new List<FileInfo>();

        for (int i = 0; i < files.Length; i++)
        {
            FileInfo file = new FileInfo(files[i]);
            list.Add(file);
        }
        return list;
    }

    /// <summary>
    /// 创建一个空的xml文件
    /// </summary>
    /// <param path="path">xml文件名</param>
    /// <param StringBuilder="data">添加数据</param>
    public static void CreateNewXml(string path, StringBuilder data = null)
    {
        XmlDocument xmlDoc = new XmlDocument();
        ////创建类型声明节点    
        XmlNode node = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "");
        ///检查文件是否存在
        if (File.Exists(path))
        {
            Console.WriteLine("该文件已存在!!");
            Debug.Log("该文件已存在!!");
            return;
        }
        else //不存在就创建
        {
            try
            {
                xmlDoc.Save(path);
                if (data != null)
                {
                    string t = data.ToString();
                    StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8);
                    sw.Write(t);
                    sw.Flush();
                    sw.Dispose();
                }
            }
            catch (Exception e)
            {
                //显示错误信息    
                Debug.Log(e.Message);
            }
        }
    }

    /// <summary>
    /// 保存数据文件
    /// </summary>
    /// <param name="fileName">文件路径</param>
    /// <param name="data">保存的数据排版</param>
    public static void SaveDateToXml(string fileName, StringBuilder data)
    {
        //检查文件是否存在
        if(!File.Exists(fileName))
            return;
        //数据转化为字符串
        string t = data.ToString();
        //找到xml文件
        StreamWriter sw = new StreamWriter(fileName, false, Encoding.UTF8);
        sw.Write(t);//写入数据
        //保存并且关闭xml文件
        sw.Flush();
        sw.Dispose();
    }

    /// <summary>
    /// 读取xml的数据
    /// </summary>
    /// <typeparam name="T">泛型</typeparam>
    /// <param name="fileName">xml的路径</param>
    /// <param name="rm">读取的数据的方法</param>
    /// <param name="data">读取数据</param>
    public static void LoadDataFromXml<T>(string fileName, ReadMethod<T> rm, ref T data)
    {
        //查找xml文件是否存在
        if(!File.Exists(fileName))
            return;
        //获取xml路径下的文件
        FileInfo file = new FileInfo(fileName);
        StreamReader sr = new StreamReader(file.OpenRead(), Encoding.UTF8);
        //委托方法
        rm(sr, ref data);
        //关闭xml文件并且释放资源
        sr.Close();
        sr.Dispose();
    }

  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值