笨木头  2017-06-11 12:26     其它     阅读(4094)     评论(2)
转载请注明,原文地址: http://www.benmutou.com/archives/2352
文章来源:笨木头与游戏开发
转载请注明,原文地址:http://www.benmutou.com/archives/2352 文章来源:笨木头与游戏开发
既然数据对象都有了,要缓存起来,真是太简单了,新建一个专门缓存CSV文件对象的类:
[cce_cs]
public class CsvDataCached_Newer
{
    /// <summary>
    /// CSVDemo.csv文件缓存对象
    /// </summary>
    public static Dictionary<int, CSVDemo> csvDemoDatas = null;

  static CsvDataCached_Newer()   {   /* 缓存CSV文件对象 */   csvDemoDatas = LoadCsvData<CSVDemo>(Application.streamingAssetsPath + "/CSVDemo.csv");   }

  /// <summary>   /// 读取CSV文件数据(利用反射)   /// </summary>   /// <typeparam name="CsvData">CSV数据对象的类型</typeparam>   /// <param name="csvFilePath">CSV文件路径</param>   /// <param name="csvDatas">用于缓存数据的字典</param>   /// <returns>CSV文件所有行内容的数据对象</returns>   private static Dictionary<int, T_CsvData> LoadCsvData<T_CsvData>(string csvFilePath)   {   Dictionary<int, T_CsvData> dic = new Dictionary<int, T_CsvData>();

  /* 从CSV文件读取数据 */   Dictionary<string, Dictionary<string, string>> result = LoadCsvFile(csvFilePath);

  /* 遍历每一行数据 */   foreach (string ID in result.Keys)   {   /* CSV的一行数据 */   Dictionary<string, string> datas = result[ID];

  /* 读取Csv数据对象的属性 */   PropertyInfo[] props = typeof(T_CsvData).GetProperties();

  /* 使用反射,将CSV文件的数据赋值给CSV数据对象的相应字段,要求CSV文件的字段名和CSV数据对象的字段名完全相同 */   T_CsvData obj = Activator.CreateInstance<T_CsvData>();

  foreach (PropertyInfo pi in props)   {   pi.SetValue(obj, Convert.ChangeType(datas[pi.Name], pi.PropertyType), null);   }

  /* 按ID-数据的形式存储 */   dic[Convert.ToInt32(ID)] = obj;   }   return dic;   }

  /// <summary>   /// 读取CSV文件   /// 结果保存到字典集合,以ID作为Key值,对应每一行的数据,每一行的数据也用字典集合保存。   /// </summary>   /// <param name="filePath"></param>   /// <returns></returns>   public static Dictionary<string, Dictionary<string, string>> LoadCsvFile(string filePath)   {   Dictionary<string, Dictionary<string, string>> result = new Dictionary<string, Dictionary<string, string>>();

  string[] fileData = File.ReadAllLines(filePath);

  if (fileData.Length < 2)   {   return result;   }

  /* CSV文件的第一行为Key字段,第二行开始是数据。第一个字段一定是ID。 */   string[] keys = fileData[0].Split(',');

  for (int i = 1; i < fileData.Length; i++)   {   string[] line = fileData[i].Split(',');   /* 以ID为key值,创建一个新的集合,用于保存当前行的数据 */

  string ID = line[0];   result[ID] = new Dictionary<string, string>();

  for (int j = 0; j < line.Length; j++)   {   /* 每一行的数据存储规则:Key字段-Value值 */   result[ID][keys[j]] = line[j];   }   }   return result;   } } [/cce_cs]
不要紧张,上面两个看起来很复杂的函数,是之前的那两个,我只是把它们移到了这个类里,并且变成了静态函数。
重点要关注的是前面两段代码:
[cce_cs]
    /// <summary>
    /// CSVDemo.csv文件缓存对象
    /// </summary>
    public static Dictionary<int, CSVDemo> csvDemoDatas = null;

  static CsvDataCached_Newer()   {   /* 缓存CSV文件对象 */   csvDemoDatas = LoadCsvData<CSVDemo>(Application.streamingAssetsPath + "/CSVDemo.csv");   }

[/cce_cs]
csvDemoDatas属性用于缓存CSVDemo文件对象,而静态构造器用于初始化这个属性。
有多少个CSV文件类型,就写多少个这样的属性。
于是,获取CSV文件对象的方式就变得很简单:
[cce_cs]
        /* 测试读取ID为2的数据 */
        CSVDemo csvDemo2 = CsvDataCached_Newer.csvDemoDatas[2];

  Debug.Log("ID=" + csvDemo2.ID + ",Name=" + csvDemo2.Name); [/cce_cs]
 
测试结果是一样的:
 其实这种缓存的方式已经不错了,接下来木头要介绍的高级缓存方式并不会比这种简单的方式方便多少。
只是,我不希望每次新增一个CSV文件,就增加一个新的属性。
所以,下一篇的高级缓存方式,大家可以不认可。
 

 
2 条评论
  • 2018-07-24 11:03:22

    private static Dictionary LoadCsvData(string csvFilePath)方法名后面为神魔要加范型,这方法怎末调用
    0回复
    • 博主 笨木头 2018-07-24 12:22:59

      /* 缓存CSV文件对象 */
      csvDemoDatas = LoadCsvData(Application.streamingAssetsPath + "/CSVDemo.csv");

      泛型代表指定的CSV文件类型
      0回复
发表评论
粤ICP备16043700号

本博客基于 BlazorAnt Design Blazor 开发