对txt配置文件的 读取架构 1

索引,文本
名字_龙飞阵,龙飞阵
名字_天覆阵,天覆阵
名字_地载阵,地载阵
名字_云垂阵,云垂阵
名字_风扬阵,风扬阵
名字_暴怒阵,暴怒阵

对于一堆这样的配置文件 ,如何对它进行解析呢?

程序的结构和表结构息息相关,这里的各个表间的衔接通过一个表索引链接起来,程序的设计也是从这里开始;

DataTable所有表结构的基类,封装了表 数据 的加载, 解析。上代码:

  1 using UnityEngine;
  2 using System;
  3 using System.Collections;
  4 using System.Collections.Generic;
  5 using System.IO;
  6 using System.Text.RegularExpressions;
  7 using System.Text;
  8 
  9 /// <summary>
 10 /// 配置表解析抽象类
 11 /// </summary>
 12 public abstract class DataTable
 13 {
 14     protected int currLineValueCount;
 15     protected string[] currLineValues;
 16     private const string FILE_ENCODING = "GBK";
 17     /// <summary>当前加载的文件路径的数组下标索引 </summary>
 18     private int fileIndex=0;
 19     private string[] filePaths;
 20     /// <summary> 以每行具体的值为键,键有空.该值的列数为值,从零开始</summary>
 21     private Dictionary<string , int> name2Index;
 22 
 23     /// <summary>
 24     /// 
 25     /// </summary>
 26     /// <param name="paths">加载文件的路径</param>
 27     public DataTable(string[] paths)
 28     {
 29         this.filePaths = paths;
 30     }
 31     public DataTable(string path)
 32     {
 33         this.filePaths = new string[] { path };
 34     }
 35 
 36     #region 数值获取
 37     /// <summary>
 38     /// 删除包含整体文本的“ ” 
 39     /// </summary>
 40     /// <param name="s">要去除“ ” 的包含的整体文本值</param>
 41     /// <returns></returns>
 42     private string deleteQuotation(string s)
 43     {
 44         //string的 索引的是char ,是特性实现的。 string的 前后 是 “”
 45         if(((s.Length>0)&&(s[0]=='"'))&&(s[s.Length-1]=='"'))
 46         {
 47             //去点第一个 和最后一个
 48             s = s.Substring(1 , s.Length - 2);
 49         }
 50         return s;
 51     }
 52 
 53     /// <summary>
 54     /// 返回的是当前行里的 Name的值 ,如果存在的话
 55     /// </summary>
 56     /// <param name="name"></param>
 57     /// <returns></returns>
 58    protected string GetValueByName(string name)
 59    {
 60        int num=0;
 61        //字典中是否已存在  索引不超过本行所在的数量 本字符串要大于零
 62        if((this.name2Index.TryGetValue(name,out num)&&(num<this.currLineValueCount))&&(this.currLineValues[num].Length>0))
 63        {
 64            string str=this.currLineValues[num];
 65            //存的 null ...
 66            if(str!="null")
 67            {
 68                return str;
 69            }        
 70        }
 71         return null;
 72    }
 73  
 74     /// <summary>
 75     /// 看当前 字典里是否存在 Name的值(是否是真是数据)
 76     /// </summary>
 77     /// <param name="name"></param>要查找的值
 78     /// <param name="defaultValue"></param>
 79     /// <param name="mustExist"></param>
 80     /// <returns></returns>
 81     protected bool GetBoolean(string name,bool defaultValue,bool mustExist)
 82    {
 83        string valueByName = this.GetValueByName(name);
 84         if(valueByName==null)
 85         {
 86             if(mustExist)
 87             {
 88                 throw new ColumnNotFoundException(name);
 89             }
 90             return defaultValue;
 91         }
 92         int result = 1;
 93         if(!int.TryParse(valueByName,out result))
 94         {
 95             throw new ParseException(valueByName);
 96         }
 97         return (result == 1);
 98    }
 99 
100     /// <summary>
101     /// 获取 一张 配置表里的 值 如果有的话
102     /// </summary>
103     /// <param name="name">要获取的string 名</param>
104     /// <param name="defaultValue">默认值</param>
105     /// <param name="mustExist"> 是否值 必须存在</param>
106     /// <returns></returns>
107     protected string GetString(string name , string defaultValue , bool mustExist)
108     {
109         string valueByName = this.GetValueByName(name);
110         if (valueByName != null)
111         {
112             return valueByName;
113         }
114         if (mustExist)
115         {
116             throw new ColumnNotFoundException(name);
117         }
118         return defaultValue;
119     }
120 
121     protected long GetLong(string name , long defaultValue , bool mustExist)
122     {
123         string valueByName = this.GetValueByName(name);
124         if (valueByName == null)
125         {
126             if (mustExist)
127             {
128                 throw new ColumnNotFoundException(name);
129             } 
130             return defaultValue;
131         }
132         long result = 0L;
133         if(!long.TryParse(valueByName,out result))
134         {
135             throw new ParseException(valueByName);
136         }
137         return result;
138     }
139     protected  double GetDouble(string name,double defaultValue ,bool mustExist)
140     {
141         string valueByName = this.GetValueByName(name);
142         if(valueByName==null)
143         {
144             if(mustExist)
145             {
146                 throw new ColumnNotFoundException(name);
147             }
148             return defaultValue;
149         }
150         double result = 0.0;
151         if(!double.TryParse(valueByName,out result))
152         {
153             throw new ParseException(valueByName);
154         }
155         return result;
156     }
157 
158     protected int GetInt(string name , int defaultValue , bool mustExist)
159     {
160         string valueByName = this.GetValueByName(name);
161         if(valueByName==null)
162         {
163             if(mustExist)
164             {
165                 throw new ColumnNotFoundException(name);
166             }
167             return defaultValue;
168         }
169         int result = 0;
170         if(!int.TryParse(valueByName,out result))
171         {
172             throw new ParseException(valueByName);
173         }
174         return result;
175     }
176 
177     protected float GetFloat(string name , float defaultValue , bool mustExist)
178     {
179         string valueByName = this.GetValueByName(name);
180         if (valueByName == null)
181         {
182             if (mustExist)
183             {
184                 throw new ColumnNotFoundException(name);
185             }
186             return defaultValue;
187         }
188         float result = 0f;
189         if (!float.TryParse(valueByName , out result))
190         {
191             throw new ParseException(valueByName);
192         }
193         return result;
194     }
195 
196     /// <summary>
197     /// 看用在哪里 ,来判断他的用处
198     /// </summary>
199     /// <param name="name"></param>
200     /// <param name="mustExist"></param>
201     /// <returns></returns>
202     protected DynamicParam GetDyncmicParam(string name, bool mustExist)
203     {
204         string s = this.GetString(name , string.Empty , mustExist);
205         int result = 0;
206         int.TryParse(s , out result);
207         double num2 = 0.0;
208         double.TryParse(s , out num2);
209         return new DynamicParam(s , result , num2);
210     }
211 
212     /// <summary>
213     /// 获取一个数据集
214     /// </summary>
215     /// <param name="name"></param>
216     /// <param name="mustExist"></param>
217     /// <returns></returns>
218     protected DataSet GetDataSet(string name,bool mustExist)
219     {
220         return new DataSet(name ,this.GetString(name,! mustExist ? string.Empty : null , mustExist));
221     }
222     #endregion
223 
224     #region 数据 类
225 
226     /// <summary>
227     /// 
228     /// </summary>
229     public class DynamicParam
230     {
231         public double f;
232         public int n;
233         public string str;
234 
235         public DynamicParam(string str_,int n_ ,double f_)
236         {
237             this.f = f_;
238             this.str = str_;
239             this.n = n_;
240         }
241     }
242 
243     /// <summary>栏数据的特殊集 </summary>
244     public class DataSet
245     {
246         private string columnName;
247         /// <summary>光标</summary>
248         private int cursor;
249 
250         /// <summary>
251         /// 取得的每一行的文本 不是通过StreamRead 的方式
252         /// </summary>
253         private MatchCollection result;
254 
255         /// <summary>当前行的 信息</summary>
256         private string[] values;
257         public DataSet(string colName,string s)
258         {
259             if(s=="")
260             {
261                 s = "\"(宝箱_金宝箱,0)\"";
262             }
263                 //(?<=\() 匹配(后面的字符, (.*?)匹配 任意多个字符 ,(?=\))匹配 )前面的字符
264                 this.result = Regex.Matches(s , @"(?<=\()(.*?)(?=\))");
265                 this.columnName = colName;       
266         }
267 
268         #region 数据获取函数
269         /// <summary>
270         /// 通过索引获取double类型的值
271         /// </summary>
272         /// <param name="index"></param>
273         /// <returns></returns>
274         public double GetDouble(int index)
275         {
276             if(index >= this.values.Length)
277             {
278                 throw new DataTable.ColumnNotFoundException(this.columnName);
279             }
280             double result = 0.0;
281             //不是能转换的格式
282             if(!double.TryParse(this.values[index],out result))
283             {
284                 throw new DataTable.ParseException(this.values[index]);
285             }
286             return result;
287         }
288 
289         public float GetFloat(int index)
290         {
291             if(index>=this.values.Length)
292             {
293                 throw new DataTable.ColumnNotFoundException(this.columnName);
294             }
295             float result = 0f;
296             if(!float.TryParse(this.values[index],out result))
297             {
298                 throw new DataTable.ParseException(this.values[index]);
299             }
300             return result;
301         }
302 
303         public int GetInt(int index)
304         {
305             if (index >= this.values.Length)
306             {
307                 throw new DataTable.ColumnNotFoundException(this.columnName);
308             }
309             int result =0;
310             if (!int.TryParse(this.values[index] , out result))
311             {
312                 throw new DataTable.ParseException(this.values[index]);
313             }
314             return result;
315         }
316 
317         public long GetLong(int index)
318         {
319             if (index >= this.values.Length)
320             {
321                 throw new DataTable.ColumnNotFoundException(this.columnName);
322             }
323             long result = 0L;
324             if (!long.TryParse(this.values[index] , out result))
325             {
326                 throw new DataTable.ParseException(this.values[index]);
327             }
328             return result;
329         }
330 
331         public string GetString(int index)
332         {
333             if (index >= this.values.Length)
334             {
335                 throw new DataTable.ColumnNotFoundException(this.columnName);
336             }
337             return this.values[index];
338         }
339         #endregion
340 
341         /// <summary>
342         /// 开放当前行的数据集
343         /// </summary>
344         /// <returns></returns>
345         public string[] Values()
346         {
347             return this.values;
348         }
349         /// <summary>
350         /// 下个值是否存在
351         /// </summary>
352         public bool NextValues()
353         {
354             //超出了行数 结束
355             if(this.cursor>=this.result.Count)
356             {
357                 return false;
358             }
359             //获取当前 行(cursor 光标所在) 的行文本
360             string str = this.result[this.cursor].Value;
361             char[] sepatator = new char[] { ',' };
362             this.values = str.Split(sepatator);
363             // 同时对当前行的文本进行处理,这样在获取瞎哥值是否存在时,也能获取当前行的值
364             for (int i=0;i<this.values.Length;i++)
365             {
366                 this.values[i] = this.values[i].Trim();
367             }
368             this.cursor++;
369             return true;
370         }
371 
372     }
373     #endregion
374 
375     #region 文件加载
376 
377     /// <summary>
378     /// isPack 是打包通过unity加载 ,否者通过 C# 加载
379     /// </summary>
380     /// <returns></returns>
381     public bool Load()
382     {
383         if (this.filePaths == null)
384         {
385             return false;
386         }
387         this.currLineValues = new string[0x400];
388         this.currLineValueCount = 0;
389         for (int i = 0 ; i < this.filePaths.Length ; i++)
390         {
391             string path = this.filePaths[i];
392             path = DataMngr._GetDirPath() + path+".txt";
393             //+DataMngr._GetExtName();
394             bool parseColumn = true;
395             if (!(!DataMngr._isPack() ? this.LoadByFile(path , parseColumn) : this.LoadByUnity(path , parseColumn)))
396             {
397                 return false;
398             }
399         }
400         this.currLineValues = null;
401         this.currLineValueCount = 0;
402         this.OnLoadComplete();
403         return true;
404     }
405 
406 
407     /// <summary>
408     /// 加载txt配置文件
409     /// </summary>
410     /// <param name="path">文件路径</param>
411     /// <param name="parseColumn">是否加载栏</param>
412     /// <returns>是否加载成功</returns>
413     private bool LoadByFile(string path,bool parseColumn)
414     {
415         FileStream stream = null;
416         try
417         {
418             stream = new FileStream(path , FileMode.Open , FileAccess.Read , FileShare.ReadWrite);
419         }
420         catch
421         {
422             return false;
423         }
424         StreamReader reader = null;
425         try
426         {
427             reader = new StreamReader(stream ,Encoding.UTF8);
428         }
429         catch
430         {//关闭流 ,取消引用
431             stream.Close();
432             stream = null;
433             return false;
434         }
435 
436         int lineNum = 0;
437         bool flag = true;
438         while(!reader.EndOfStream)
439         {
440             string lineStr = reader.ReadLine();
441             //
442             if(lineNum==0)
443             {
444                 if(parseColumn)
445                 {//第一栏
446                     this.ParseColumn(lineStr);
447                 }
448             }
449             else if(!this.ParseData(lineStr,lineNum))
450             {//转换出错
451                 flag = false;
452                 Debug.LogError(string.Concat(new string[]{"file parse error.path=",path,",line=",lineNum.ToString()}));
453                 break;
454             }
455             lineNum++;
456         }
457         reader.Close();
458         reader = null;
459         stream.Close();
460         stream = null;
461         return flag;
462     }
463 
464     private bool LoadByUnity(string path,bool parseColumn)
465     {
466         int num3=0;
467         //所有资源打包为AssetsBundle 然后通过路径加载
468         Res res = ResMngr.GetInstance().LoadSync("Data" , path);
469         if(res==null)
470         {
471             return false;
472         }
473         TextAsset assetToUnload = (TextAsset)res.GetObject();
474         if(assetToUnload==null)
475         {
476             return false;
477         }
478         string text = assetToUnload.text;
479         if(text.Length<=0)
480         {
481             return false;
482         }
483         //Windows中每行结尾是“<换行><回车>”,即“\n\r”
484         string str2 = "\r\n";
485         int lineNum = 0;
486         for(int i=0;i<text.Length;i=num3+str2.Length)
487         {
488             //OrdinalIgnoreCase使用序号排序规则并忽略被比较字符串的大小写,对字符串进行比较
489             num3 = text.IndexOf(str2 , i , StringComparison.OrdinalIgnoreCase);
490             string lineStr = text.Substring(i , num3 - i);
491             if(lineNum==0)
492             {
493                 if(parseColumn)
494                 {
495                     this.ParseColumn(lineStr);
496                 }
497             }
498             else if(!this.ParseData(lineStr,lineNum))
499             {
500                 return false;
501             }
502             lineNum++;
503         }
504         Resources.UnloadAsset(assetToUnload);
505         return true;
506 
507     }
508 
509     //public bool LoadNotFromDataMngr()
510     //{
511     //    if(this.filePaths==null)
512     //    {
513     //        return false;
514     //    }
515     //     0x400 == 1024
516     //    this.currLineValues = new string[0x400];
517     //    this.currLineValueCount = 0;
518     //    string str = string.Empty;
519     //    string serverDataPath = string.Empty;
520     //    bool flag = false;
521     //    if(RunParam.Getins)
522 
523 
524     //}
525 
526     /// <summary>
527     ///转换第一行的栏 
528     /// </summary>
529     /// <param name="lineStr">当前行的文本,这里是第一行栏的文本</param>
530     protected void ParseColumn(string lineStr)
531     {
532         this.name2Index = new Dictionary<string , int>();
533         //文本的分割器
534         char[] separator = new char[] { ',' };
535         string[] strArray = lineStr.Split(separator);
536         for(int i=0;i<strArray.Length;i++)
537         {
538             //每行的每个值作为 键 
539             string key = strArray[i];
540             //作为栏 是一定不会键位空值的
541             if(this.name2Index.ContainsKey(key))
542             {
543                 Debug.LogError("File["+this.filePaths[this.fileIndex]+"]colum["+key+"]had exist!");
544                 return;
545             }
546             this.name2Index.Add(key , i);
547         }
548     }
549 
550     /// <summary>
551     /// 转换每个配置表里的值 
552     /// </summary>
553     /// <param name="lineStr">每行的文本</param>
554     /// <param name="lineNum">文本的所在行位置,第几行</param>
555     /// <returns>GetBoolean 函数定义了抛出异常的条件,这里扑捉异常</returns>
556     protected bool ParseData(string lineStr,int lineNum)
557     {
558         try
559         {
560             //行开头以"//"始 是一个完整的文本
561             if(lineStr.Substring(0,2).Equals("//"))
562             {
563                 return true;
564             }
565         }
566         catch(Exception)
567         {
568             //这行数据为空 会报错哦
569             Debug.LogError("ParseData Exception");
570         }
571         //这里进行 数据的转换 ,包括格式定义的检查 分割,并给当前行赋值
572         this.currLineValueCount = this.SplitColumn(lineStr);
573         try
574         {
575            if(!this.OnParseLine(lineNum))
576            {
577                Debug.LogError(string.Concat(new string[] { "File[" , this.GetFilePath() , "]Line[" , lineNum.ToString() , "]prototype may had exist!" }));
578                return false;
579            }
580         }
581         catch(ColumnNotFoundException ex)
582         {
583             Debug.LogError(string.Concat(new string[] { "Line[" , lineNum.ToString() , "]could not find\"" , ex.GetColumnName() , "\"column!" }));
584             return false;
585         }
586         catch(ParseException ex1)
587         {
588             Debug.LogError(string.Concat(new string[] { "Line[" , lineNum.ToString() , "]parse failed ! data=\"" , ex1.GetParseData() , "\"" }));
589             return false;
590         }
591         return true;
592     }
593 
594     public string GetFilePath()
595     {
596         return this.filePaths[this.fileIndex];
597     }
598 
599     /// <summary>
600     /// 获取栏数,并对栏进行处理,对于有‘”’标记整体的栏值 去‘“’ 处理,currentValues 也一并处理了
601     /// </summary>
602     /// <param name="lineStr">当前的一行文本</param>
603     /// <returns></returns>
604     private int SplitColumn(string lineStr)
605     {
606         int num = 0;
607         bool flag = false;
608         int startIndex = 0;
609         for(int i=0;i<lineStr.Length;i++)
610         {
611             char ch = lineStr[i];
612             //文本中字符包含 “ 见文本char_rate_params.txt 这是被标记的文本,其中包含‘,’但是是一个整体要特殊处理
613             if(ch=='"')
614             {
615                 flag = !flag;
616             }
617                 //有 段落值标记时,该段内只一个整体 不对‘,’进行分割
618             else if((ch==',')&&!flag)
619             {
620                 string s = lineStr.Substring(startIndex , i - startIndex);
621                 startIndex = i + 1;
622                 this.currLineValues[num++] = this.deleteQuotation(s);
623             }
624         }
625         //不是用Split 分割 ,最后一个‘,’之后 不会再分割,还要再加上去
626         if(startIndex<lineStr.Length)
627         {
628             string str2 = lineStr.Substring(startIndex , lineStr.Length - startIndex);
629             this.currLineValues[num++] = this.deleteQuotation(str2);
630         }
631         return num;
632     }
633 
634 
635 
636     /// <summary>
637     /// 转换行
638     /// </summary>
639     /// <param name="lineNum">文本所在行数</param>
640     /// <returns></returns>
641     protected abstract bool OnParseLine(int lineNum);
642     /// <summary>
643     /// 构建表数据
644     /// </summary>
645     /// <returns></returns>
646     public abstract bool OnBuild();
647 
648     protected abstract bool OnLoadComplete();
649     #endregion 
650 
651     #region 异常类
652     public class ParseException:Exception
653     {
654         private string data;
655         public ParseException(string d)
656         {
657             this.data = d;
658         }
659         public string GetParseData()
660         {
661             return this.data;
662         }
663     }
664     public class ColumnNotFoundException:Exception
665     {
666         private string columnName;
667         public ColumnNotFoundException(string name)
668         {
669             this.columnName = name;
670         }
671         public string GetColumnName()
672         {
673             return this.columnName;
674         }
675     }
676     #endregion
677 
678 }
View Code

 

posted @ 2015-11-28 01:44  bambom  阅读(380)  评论(0编辑  收藏  举报