Unity3D 异步读取CSV文件

发表于2016-01-24
评论5 3.8k浏览

       误打误撞在VR圈混迹多年,终于下决心要回来做MMOARPG手游了。

       很久没有这么“充实”过了,项目进度又到了读表阶段了。

       看到前些年使用的CSV读取工具类还有优化空间,所以修改后发出来跟大家交流交流,还望各路大神多加指点。

       注释都在代码里,so,废话不多说直接上代码:

<font color="#000"><font face="Arial">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);  

    }  

}  </font></font><font color="#000"><font face="Arial">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);  

    }  

}  </font></font>


       下面是使用方法:

<font color="#000"><font face="Arial">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);  

    }  

}  </font></font>

       嗯,就是这样,我忙去了~~汪汪~!

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引