原创文章如需转载请注明:转载自 脱莫柔Unity3D学习之旅 Unity3D引擎技术交流QQ群:【119706192】本文链接地址: Unity3D 异步读取CSV文件 |
误打误撞在VR圈混迹多年,终于下决心要回来做MMOARPG手游了。
很久没有这么“充实”过了,项目进度又到了读表阶段了。
看到前些年使用的CSV读取工具类还有优化空间,所以修改后发出来跟大家交流交流,还望各路大神多加指点。
注释都在代码里,so,废话不多说直接上代码:
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using System.Text; /// <summary> /// 读取CSV工具类 /// (需求:UTF-8格式) /// </summary> public class LoadCSVData : MonoBehaviour { public delegate void toDirectoryCallBack(Dictionary<string, List<string>> csvdata); /// <summary> /// 异步开始读取CSV文档 /// </summary> /// <param name="Filename">StreamingAssets目录内的文件名</param> /// <param name="LoadCBK">读取完成后的回调事件</param> /// <returns></returns> public IEnumerator LoadCSV_toDirectory(string Filename,toDirectoryCallBack LoadCBK) { string CSVText = null; yield return StartCoroutine(LoadWWW(GetFilepath(Filename), (www) => { CSVText = www; })); Dictionary<string, List<string>> CSVData = getDirectory(readcsv(CSVText.ToString())); LoadCBK(CSVData); } /// <summary> /// 获取完整的文件路径 /// </summary> /// <param name="Filename"></param> /// <returns></returns> string GetFilepath(string Filename) { switch (Application.platform) { case RuntimePlatform.Android: return "jar:file://" + Application.dataPath + "!/assets/" + Filename + ".csv"; case RuntimePlatform.IPhonePlayer: return Application.dataPath + "/Raw/" + Filename + ".csv"; default: return "file://" + Application.dataPath + "/StreamingAssets/" + Filename + ".csv"; } } /// <summary> /// 读取文件 /// </summary> /// <param name="filepath">文件路径</param> /// <param name="loadCBK">读取完成回调</param> /// <returns></returns> IEnumerator LoadWWW(string filepath, Action<string> loadCBK) { WWW www = new WWW(filepath); yield return www; string CSVText; if (!string.IsNullOrEmpty(www.error)) { CSVText = www.error; } else { CSVText = www.text; } loadCBK(CSVText); } public static List<List<string>> readcsv(string strin) { return readcsv(strin, Encoding.UTF8); } public static List<List<string>> readcsv(string strin, Encoding encoding) { List<List<string>> ret = new List<List<string>>(); strin = strin.Replace("\r", ""); string[] lines = strin.Split('\n'); if (lines.Length > 0) { byte[] byt = encoding.GetBytes(lines[0]); if (byt.Length >= 3 && byt[0] == 0xEF && byt[1] == 0xBB && byt[2] == 0xBF) { lines[0] = encoding.GetString(byt, 3, byt.Length - 3); } } for (int i = 0; i < lines.Length; i++) { if (string.IsNullOrEmpty(lines[i]) || lines[i].StartsWith("#")) continue; List<string> s = split(lines[i], encoding); ret.Add(s); } return ret; } static List<string> split(string line, Encoding encoding) { byte[] b = encoding.GetBytes(line); List<string> bls = new List<string>(); int end = b.Length - 1; List<byte> bl = new List<byte>(); bool inQuote = false; for (int i = 0; i < b.Length; i++) { switch ((char)b[i]) { case ',': if (inQuote) bl.Add(b[i]); else { bls.Add(makefield(ref bl, encoding)); bl.Clear(); } break; case '"': inQuote = !inQuote; bl.Add((byte)'"'); break; case '\\': if (i < end) { switch ((char)b[i + 1]) { case 'n': bl.Add((byte)'\n'); i++; break; case 't': bl.Add((byte)'\t'); i++; break; case 'r': i++; break; default: bl.Add((byte)'\\'); break; } } else bl.Add((byte)'\\'); break; default: bl.Add(b[i]); break; } } bls.Add(makefield(ref bl, encoding)); bl.Clear(); return bls; } static string makefield(ref List<byte> bl, Encoding encoding) { if (bl.Count > 1 && bl[0] == '"' && bl[bl.Count - 1] == '"') { bl.RemoveAt(0); bl.RemoveAt(bl.Count - 1); } int n = 0; while (true) { if (n >= bl.Count) break; if (bl[n] == '"') { if (n < bl.Count - 1 && bl[n + 1] == '"') { bl.RemoveAt(n + 1); n++; } else bl.RemoveAt(n); } else n++; } return encoding.GetString(bl.ToArray()); } /// <summary> /// 转换成Dictionary类型 /// </summary> /// <param name="listin"></param> /// <returns></returns> public static Dictionary<string, List<string>> getDirectory(List<List<string>> listin) { Dictionary<string, List<string>> dir = new Dictionary<string, List<string>>(); for (int i = 0; i < listin.Count; i++) { if (string.IsNullOrEmpty(listin[i][0])) continue; dir[listin[i][0]] = listin[i]; } return dir; } /// <summary> /// 打印 Csv 转换的二维数组 /// </summary> /// <param name="grid"></param> public static void DebugOutputGrid(string _titleName, Dictionary<string, List<string>> grid) { StringBuilder textOutput = new StringBuilder(); textOutput.Append(_titleName); textOutput.Append("\n"); foreach (var line in grid) { for (int i = 0; i < line.Value.Count; i++) { string row = line.Value[i]; textOutput.Append(row); if (i < line.Value.Count - 1) textOutput.Append("|"); } textOutput.Append("\n"); } Debug.Log(textOutput); } }
using UnityEngine; using System.Collections; using System; using System.Collections.Generic; public class LoadCSVDara_debug : MonoBehaviour { // Use this for initialization void Start () { StartCoroutine(loading()); } IEnumerator loading() { yield return StartCoroutine(LoadCSVData_debug()); } /// <summary> /// 读取CSV格式的文档 /// </summary> /// <returns></returns> IEnumerator LoadCSVData_debug() { DateTime startTime = DateTime.Now; Debug.Log("开始读取数据"); LoadCSVData loadcsv = gameObject.AddComponent<LoadCSVData>(); Dictionary<string, List<string>> data = null; //读取技能表 yield return StartCoroutine(loadcsv.LoadCSV_toDirectory("SKILL", (csvdata) => { data = csvdata; })); Debug.Log("读取技能表花费:" + (DateTime.Now - startTime).TotalMilliseconds + "ms"); //SkillInfo.loadSkillDatas(data); LoadCSVData.DebugOutputGrid("技能表", data); } }