Unity3D 异步读取CSV文件

原创文章如需转载请注明:转载自 脱莫柔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);
    }
}

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

你可能感兴趣的:(异步读取SCV)