解析txt数据文件,通过获取对象属性的名字自动匹配

说明:写了一个通用的txt解析类,通过获取对象属性的名字使用txt数据自动初始化对象。

直接看获取数据的代码调用:

public class TestTxtDataAnalysis : MonoBehaviour {
	void Start () {

            // 遍历道具和武器数据集合,输出ID和名字
        for (int i = 1; i <= PropAndWeaponData.DicData.Count; i++)
        {
            Debug.Log("ID:" +  PropAndWeaponData.DicData[i].Id + "   名字:" + PropAndWeaponData.DicData[i].Name);
        }
	}	
}

结果(只截部分):

然后再来看具体实现:

一、txt文件的配置

1、用CSV格式文件配置好数据。

2、将CSV另存为txt文件,或者直接复制一份,修改为txt格式。修改编码格式为utf-8无bom。

txt文件内容如下:

Id,Name,Desc,Type,Icon,Mod,Atk,AtkSpeed,CostMp,MaxAtkRange,AtkOffset,MaxThroughTargetNum,HitBackDis,BulletSpeed,CanBoom,BoomRange,BulletEffect,ExtraEffectId
1,基因点,货币,3,icon,Mod,0,0,0,0,0,0,0,0,0,0,0,0
2,蓝瓶,恢复药品,4,icon,Mod,0,0,0,0,0,0,0,0,0,0,0,0
3,红瓶,恢复药品,4,icon,Mod,0,0,0,0,0,0,0,0,0,0,0,0
4,单手枪,单手枪,11,icon,Mod,3,0.5,5,5,5,5,5,5,1,5,5,5
5,双手枪,双手枪,12,icon,Mod,3,0.5,5,5,5,5,5,5,1,5,5,5
6,刺枪,刺枪,13,icon,Mod,3,0.5,5,5,5,5,5,5,1,5,5,5
7,单手剑,单手剑,14,icon,Mod,3,0.5,1,2,3,4,5,6,1,2,3,4

二、PropAndWeaponData类

注意:自定义属性的名字必须和txt配置文件一致。

// 道具和武器数据表
public class PropAndWeaponData : TxtDataBase<PropAndWeaponData>
{

    public const string DATA_PATH = "Data/ConfigData_PropAndWeapon";    // txt数据文件路径

    // 自定义属性。注意:属性名字必须和txt数据文件的第一行的属性名完全一致
    public int Id{ set; get; }
    public string Name{ set; get; }  // 名字
    public string Desc{ set; get; }  // 描述
    //public PropAndWeaponType Type{ set; get; }  // 类型
    public int Type { set; get; }  // 类型
    public string Icon{ set; get; }  // 
    public string Mod{ set; get; }  // 
    // 武器属性
    public int Atk{ set; get; }  // 攻击力
    public float AtkSpeed{ set; get; }  // 攻速
    public float CostMp{ set; get; }  // 耗蓝
    public float MaxAtkRange{ set; get; }  // 最大射程
    public float AtkOffset{ set; get; }  // 攻击的子弹偏移

    public int MaxThroughTargetNum{ set; get; }  // 子弹最大击穿目标数
    public float HitBackDis{ set; get; }  // 击退距离
    public float BulletSpeed{ set; get; }  // 子弹速度
    public float CanBoom{ set; get; }  // 能否爆炸,1是,0否
    public float BoomRange{ set; get; }  // 爆炸范围

    public string BulletEffect{ set; get; }  // 子弹特效
    public int ExtraEffectId{ set; get; }  // 附加特效ID



    #region 道具和武器类型
    public enum PropAndWeaponType {
        Coin = 3,   // 货币
        RecoveryProducts = 4,   // 恢复用品
        SingleGun = 11,  // 单手枪
        TwoHandGun = 12,  // 双手枪
        StabGun = 11,  // 刺枪
        OneHandSword = 12,  // 单手剑
    }
    #endregion
}

三、txt解析类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using System;
using System.Linq.Expressions;
using System.Text;  // stringBuilding 需要
using System.Reflection;    // 反射

public class TxtDataBase<T> where T: TxtDataBase<T>, new()
{
    private static Dictionary<int, T> dicData = null;   // 储存数据集合

        // 初始化
    private static void Init()
    {
        dicData = new Dictionary<int, T>();    // 初始化集合

        AnalysisTxtToDic();     // 解析数据表txt数据到集合中
    }

    // 储存数据集合
    public static Dictionary<int, T> DicData
    {
        get
        {
            if(dicData == null)
            {
                Init(); // 初始化
            }
            return dicData;
        }
    }


    /// <summary>
    /// 解析数据表txt数据到集合中
    /// </summary>
    private static void AnalysisTxtToDic()
    {
        // 根据属性名字获取数据文件路径的值
        Type type = typeof(T);
        FieldInfo fileNameField = type.GetField("DATA_PATH");   
        if (fileNameField == null)
            return;
        string strDataPath = fileNameField.GetValue(null) as string;

        if (string.IsNullOrEmpty(strDataPath))
            return;

        //读取txt文件,有中文时,txt文件必须为utf-8无bom格式
        TextAsset binAsset = Resources.Load(strDataPath, typeof(TextAsset)) as TextAsset;
        if(binAsset == null)
        {
            Debug.LogError("txt文件为空,请检查。 文件路径:" + strDataPath);
            return;
        }

        //读取每一行的内容  
        string[] lineArray = binAsset.text.Split('\n');
        for (int i = 0; i < lineArray.Length; i++)
        {
            // 所有行,去掉末尾的换行符,前面已经去掉'\n'了,这里再去掉\r就行了
            lineArray[i] = lineArray[i].TrimEnd((char[])"\r".ToCharArray());
        }

        string strFirstLine = lineArray[1];
        string[] arrayPoperty = strFirstLine.Split(','); // 用于储存首行的拆分的所有属性
        string[] tempArray; // 用于储存一行拆分的所有数据
                            // 将每行拆分的数据赋值给对应对象的参数
        for (int i = 0; i < lineArray.Length; i++)
        {
            if (i == 0)
                continue;

            if (string.IsNullOrEmpty(lineArray[i])) // 最后一行可能为空
            {
                break;
            }

            tempArray = lineArray[i].Split(',');    // 根据逗号分隔内容

            // 输出拆分数据
            //foreach (var item in tempArray)
            //{
            //    Debug.Log("item=" + item);
            //}

            InitDataInDic_ByName(arrayPoperty, tempArray); // 将每行拆分的数据赋值给对应对象的参数(通过获取变量的名字自动匹配),并存储到集合中
        }
    }

    /// <summary>
    /// 将每行拆分的数据赋值给对应对象的参数(通过获取对象属性的名字自动匹配),并存储到集合中
    /// 注意:对象属性的名字必须和配置文件中第一行的属性名字完全一致。
    /// </summary>
    /// <param name="arrayProperty">属性数组</param>
    /// <param name="arrayValue">值数组</param>
    private static void InitDataInDic_ByName(string[] arrayProperty, string[] arrayValue)
    {
        //Debug.Log(GetType() + "/InitPropAndWeaponDataInDic_ByName");
        T propData = new T();

        string[] strTempArray;
        Vector3 vector3Temp;

        foreach (System.Reflection.PropertyInfo p in propData.GetType().GetProperties())    // 遍历自定义对象的属性(注意:不能遍历字段和方法)
        {
            System.Reflection.PropertyInfo setobj = propData.GetType().GetProperty(p.Name);   //搜索具有指定属性名称的公共属性

            //Debug.Log("Name:= " + p.Name + "  Value: =" + p.GetValue(s, null));
            //Debug.Log("setobj=" + setobj);
            //Debug.Log("setobj=" + setobj.PropertyType);   // 

            for (int i = 0; i < arrayProperty.Length; i++)  // 遍历解析的属性数组
            {
                if (arrayProperty[i].Equals(p.Name))    // 当属性数组里的属性类型 和 公共属性一致,则对公共属性进行赋值(先根据数据类型进行转换)
                {
                    if (arrayValue[i] != null && setobj != null)
                    {
                        if (setobj.PropertyType.Equals(typeof(string))) // 判断公共属性的数据类型
                        {
                            setobj.SetValue(propData, arrayValue[i], null);
                        }
                        else if (setobj.PropertyType.Equals(typeof(int)))
                        {
                            setobj.SetValue(propData, Convert.ToInt32(arrayValue[i]), null);
                        }
                        else if (setobj.PropertyType.Equals(typeof(float)))
                        {
                            setobj.SetValue(propData, float.Parse(arrayValue[i]), null);
                        }
                        else if (setobj.PropertyType.Equals(typeof(bool)))  // 布尔值,配置表为1表示true,为0表示为false
                        {
                            if(Convert.ToInt32(arrayValue[i]) == 1)
                                setobj.SetValue(propData, true, null);
                            else
                                setobj.SetValue(propData, false, null);
                        }
                        else if (setobj.PropertyType.Equals(typeof(int[]))) // 整形数组
                        {
                            if (arrayValue[i].Contains("|"))
                            {
                                strTempArray = arrayValue[i].Split('|');    // 整形数组以'|'分隔
                                int[] tempArray = new int[strTempArray.Length];
                                for (int m = 0; m < strTempArray.Length; m++)
                                {
                                    tempArray[m] = Convert.ToInt32(strTempArray[m]);
                                }
                                setobj.SetValue(propData, tempArray, null);
                            }
                            else
                            {
                                int[] tempArray = { Convert.ToInt32(arrayValue[i])};
                                setobj.SetValue(propData, tempArray, null);
                            }

                        }
                        else if (setobj.PropertyType.Equals(typeof(Vector3))) // Vector3
                        {
                            if (arrayValue[i].Contains("|"))
                            {
                                strTempArray = arrayValue[i].Split('|');    // Vector3以'|'分隔
                                vector3Temp.x = float.Parse(strTempArray[0]);
                                vector3Temp.y = float.Parse(strTempArray[1]);
                                vector3Temp.z = float.Parse(strTempArray[2]);
                                setobj.SetValue(propData, vector3Temp, null);
                            }
                            else
                            {
                                Debug.LogError("InitDataInDic_ByName/" + "Vector3类型数据错误");
                            }

                        }
                    }
                    //Debug.Log("Name = " + p.Name + "  Value =" + p.GetValue(propData, null));
                    break;
                }
            }
        }
        dicData.Add(Convert.ToInt32(arrayValue[0]), propData);  // 添加到集合中

        // 打日志,展示解析后的数据
        DisplayAnalysisData(propData);    // 测试数据读取是否正确,可以打开这行注释
    }

    /// <summary>
    /// 展示解析后的数据
    /// </summary>
    private static void DisplayAnalysisData(T tObject)
    {
        //Debug.Log("TxtDataBase/DisplayTxtData");

        foreach (System.Reflection.PropertyInfo p in tObject.GetType().GetProperties())    // 遍历自定义对象的属性(注意:不能遍历字段和方法)
        {
            System.Reflection.PropertyInfo setobj = tObject.GetType().GetProperty(p.Name);   //搜索具有指定属性名称的公共属性

            Debug.Log("Name:= " + p.Name + "  Value: =" + p.GetValue(tObject, null));
            //Debug.Log("setobj=" + setobj);
            //Debug.Log("setobj=" + setobj.PropertyType);   // 
        }

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值