Unity数据解析(Json、XML、CSV、二进制)

注释

常见的数据解析(Json、XML、CSV、二进制)

cpp 复制代码
using System;
using System.IO;
using System.Xml.Serialization;
using Newtonsoft.Json;
using System.Runtime.InteropServices;
using System.Text;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;

/// <summary>
/// 数据解析(Json、XML、CSV、二进制)
/// </summary>
public class AnalyticData
{
    #region Json
    /// <summary>
    /// Json序列化接口
    /// </summary>
    /// <typeparam name="T">泛型类</typeparam>
    /// <param name="dataClass">序列化对象</param>
    /// <returns></returns>
    public static string JsonSerialization<T>(T dataClass) where T : class
    {
        string jsonStr = JsonConvert.SerializeObject(dataClass);
        return jsonStr;
    }

    /// <summary>
    /// Json反序列化接口
    /// </summary>
    /// <typeparam name="T">泛型类</typeparam>
    /// <param name="path">文件路径</param>
    /// <returns></returns>
    public static T JsonRead<T>(string path) where T : class
    {
        T Data;
        StreamReader sr = new StreamReader(path);
        string jsonStr = sr.ReadToEnd();
        //反序列化
        Data = JsonConvert.DeserializeObject<T>(jsonStr);
        return Data;
    }

    /// <summary>
    /// Json反序列化接口(数组类型)
    /// </summary>
    /// <typeparam name="T">泛型类</typeparam>
    /// <param name="path">文件路径</param>
    /// <returns></returns>
    public static T[] JsonArrayRead<T>(string path) where T : class
    {
        T[] DataArray;
        StreamReader sr = new StreamReader(path);
        string jsonStr = sr.ReadToEnd();
        //反序列化
        DataArray = JsonConvert.DeserializeObject<T[]>(jsonStr);
        return DataArray;
    }

    /// <summary>
    /// Json反序列化接口
    /// </summary>
    /// <typeparam name="T">泛型类</typeparam>
    /// <param name="str">需解析字符串</param>
    /// <returns></returns>
    public static T JsonByStringRead<T>(string str) where T : class
    {
        T Data;
        //反序列化
        Data = JsonConvert.DeserializeObject<T>(str);
        return Data;
    }
    #endregion

    #region XML
    /// <summary>
    /// XML序列化接口
    /// </summary>
    /// <typeparam name="T">泛型类</typeparam>
    /// <param name="dataClass">序列化对象</param>
    /// <returns></returns>
    public static string XMLSerialization<T>(T dataClass) where T : class
    {
        using (StringWriter sw = new StringWriter())
        {
            //此处T必须是Public类型
            Type t = dataClass.GetType();
            XmlSerializer serializer = new XmlSerializer(dataClass.GetType());
            serializer.Serialize(sw, dataClass);
            sw.Close();
            return sw.ToString();
        }
    }

    /// <summary>
    /// XML序列化接口(元素值序列化为单引号格式)
    /// </summary>
    /// <typeparam name="T">泛型类</typeparam>
    /// <param name="dataClass">序列化对象</param>
    /// <returns></returns>
    public static string XMLToSingleQuotationMarkSerialization<T>(T dataClass) where T : class
    {
        using (StringWriter sw = new StringWriter())
        {
            //此处T类必须是Public类型
            Type t = dataClass.GetType();
            XmlSerializer serializer = new XmlSerializer(dataClass.GetType());
            serializer.Serialize(sw, dataClass);
            sw.Close();

            string dataStr = sw.ToString();
            string newDataStr = dataStr.Replace("\"", "'");   //将双引号转换为单引号,方便部分引擎解析
            return newDataStr;
        }
    }
    //转义字符:(当属性值中含特殊字符时,为避免解析出错,需使用转义字符)
    //1、 &lt;      <      小于号 
    //2、 &gt;      >      大于号
    //3、 &amp;     &      和
    //4、 '    '      单引号
    //5、 &quot;    "      双引号
    //6、 &lt;=     <=     小于等于
    //7、 &gt;=     >=     大于等于


    /// <summary>
    /// XML反序列化接口
    /// </summary>
    /// <typeparam name="T">泛型类</typeparam>
    /// <param name="path">文件路径</param>
    /// <returns></returns>
    public static T XMLRead<T>(string path) where T : class
    {
        StreamReader sReader = new StreamReader(path);
        string xmlStr = sReader.ReadToEnd();
        try
        {
            using (StringReader sr = new StringReader(xmlStr))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                return serializer.Deserialize(sr) as T;
            }
        }
        catch (Exception)
        {
            return null;
        }
    }
    #endregion

    #region CSV
    private static char _csvSeparator = ',';
    private static bool _trimColumns = false;

    //解析一行
    private static List<string> ParseLine(string line)
    {
        StringBuilder _columnBuilder = new StringBuilder();
        List<string> Fields = new List<string>();
        bool inColum = false; //是否是在一个列元素里
        bool inQuotes = false; //是否需要转义
        bool isNotEnd = false; //读取完毕未结束转义
        _columnBuilder.Remove(0, _columnBuilder.Length);

        //空行也是一个空元素,一个逗号是2个空元素
        if (line == "")
        {
            Fields.Add("");
        }
        // Iterate through every character in the line  遍历行中的每个字符
        for (int i = 0; i < line.Length; i++)
        {
            char character = line[i];

            //If we are not currently inside a column   如果我们现在不在一列中
            if (!inColum)
            {
                // If the current character is a double quote then the column value is contained within
                //如果当前字符是双引号,则列值包含在内
                // double quotes, otherwise append the next character
                //双引号,否则追加下一个字符
                inColum = true;
                if (character == '"')
                {
                    inQuotes = true;
                    continue;
                }
            }
            // If we are in between double quotes   如果我们处在双引号之间
            if (inQuotes)
            {
                if ((i + 1) == line.Length) //这个字符已经结束了整行
                {
                    if (character == '"') //正常转义结束,且该行已经结束
                    {
                        inQuotes = false;
                        continue;
                    }
                    else //异常结束,转义未收尾
                    {
                        isNotEnd = true;
                    }
                }
                else if (character == '"' && line[i + 1] == _csvSeparator) //结束转义,且后面有可能还有数据
                {
                    inQuotes = false;
                    inColum = false;
                    i++; //跳过下一个字符
                }
                else if (character == '"' && line[i + 1] == '"') //双引号转义
                {
                    i++; //跳过下一个字符
                }
                else if (character == '"') //双引号单独出现(这种情况实际上已经是格式错误,为了兼容暂时不处理)
                {
                    throw new System.Exception("格式错误,错误的双引号转义");
                }
                //其他情况直接跳出,后面正常添加
            }
            else if (character == _csvSeparator)
            {
                inColum = false;
            }
            // If we are no longer in the column clear the builder and add the columns to the list
            ///   结束该元素时inColumn置为false,并且不处理当前字符,直接进行Add
            if (!inColum)
            {
                Fields.Add(_trimColumns ? _columnBuilder.ToString().Trim() : _columnBuilder.ToString());
                _columnBuilder.Remove(0, _columnBuilder.Length);
            }
            else //追加当前列
            {
                _columnBuilder.Append(character);
            }
        }

        // If we are still inside a column add a new one (标准格式一行结尾不需要逗号结尾,而上面for是遇到逗号才添加的,为了兼容最后还要添加一次)
        if (inColum)
        {
            if (isNotEnd)
            {
                _columnBuilder.Append("\r\n");
            }
            Fields.Add(_trimColumns ? _columnBuilder.ToString().Trim() : _columnBuilder.ToString());
        }
        else //如果inColumn为false,说明已经添加,因为最后一个字符为分隔符,所以后面要加上一个空元素
        {
            Fields.Add("");
        }
        return Fields;
    }

    /// <summary>
    /// 读取CSV文件
    /// </summary>
    /// <param name="filePath"></param>
    /// <param name="encoding"></param>
    /// <returns></returns>
    public static List<List<string>> CSVRead(string filePath, Encoding encoding)
    {
        List<List<string>> result = new List<List<string>>();
        string content = File.ReadAllText(filePath, encoding); //读取所有的文本内容
        string[] lines = content.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
        //以换行回车拆分字符串,去除空格
        //注:回车换行可能对某些文本不适用,这里如果我们出现读取不正常,可以改用 \n (换行)试试

        for (int i = 0; i < lines.Length; i++)
        {
            List<string> line = ParseLine(lines[i]);
            result.Add(line);
        }
        return result;
    }

    /// <summary>
    /// 生成CSV文件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dataList">对象集合</param>
    /// <param name="filePath">文件存储路径</param>
    /// <returns></returns>
    public static bool CSVFileSaveData<T>(List<T> dataList, string filePath) where T : class
    {
        bool successFlag = true;

        //所有文本
        StringBuilder sb_Text = new StringBuilder();
        //第一行属性文本
        StringBuilder strColumn = new StringBuilder();
        //其他行属性值文本
        StringBuilder strValue = new StringBuilder();
        StreamWriter sw = null;
        var tp = typeof(T);
        //获取当前Type的所有公共属性                   BindingFlags指定反射查找的范围
        PropertyInfo[] props = tp.GetProperties(BindingFlags.Public | BindingFlags.Instance);


        try
        {
            //获取第一行属性文本
            for (int i = 0; i < props.Length; i++)
            {
                var itemPropery = props[i];
                //检索自定义特性信息
                AttrForCsvColumnLabel labelAttr = itemPropery.GetCustomAttributes(typeof(AttrForCsvColumnLabel), true).FirstOrDefault() as AttrForCsvColumnLabel;
                if (labelAttr != null)
                {
                    strColumn.Append(labelAttr.Title);
                }
                else
                {
                    strColumn.Append(props[i].Name);
                }
                strColumn.Append(",");
            }
            //移除最后一个","
            strColumn.Remove(strColumn.Length - 1, 1);
            sb_Text.AppendLine(strColumn.ToString());

            //依次遍历数据列表,得到其他行属性值文本
            for (int i = 0; i < dataList.Count; i++)
            {
                var model = dataList[i];
                strValue.Clear();
                //获取每一组数据中对应的属性值
                for (int m = 0; m < props.Length; m++)
                {
                    var itemProoery = props[m];
                    var val = itemProoery.GetValue(model, null);
                    if (m == 0)
                    {
                        strValue.Append(val);
                    }
                    else
                    {
                        strValue.Append(",");
                        strValue.Append(val);
                    }
                }
                sb_Text.AppendLine(strValue.ToString());
            }
        }
        catch (System.Exception)
        {
            successFlag = false;
        }
        finally
        {
            if (sw != null)
            {
                sw.Dispose();
            }
        }
        File.WriteAllText(filePath, sb_Text.ToString(), Encoding.Default);
        return successFlag;
    }


    public static void CsvWrite(List<List<string>> datas, string path)
    {
        //所有文本
        StringBuilder sb_Text = new StringBuilder();
        for (int i = 0; i < datas.Count; i++)
        {
            for (int j = 0; j < datas[i].Count; j++)
            {
                sb_Text.Append(datas[i][j] + ",");
            }
            sb_Text.AppendLine();
        }
        File.WriteAllText(path, sb_Text.ToString(), Encoding.Default);
    }

    #endregion

    #region 结构体二进制
    /// <summary>
    /// 结构体转换为二进制数组
    /// </summary>
    /// <param name="structObj">结构体</param>
    /// <returns>转换后的二进制数组</returns>
    public static byte[] StructToBytesFunc(object structObj)
    {
        //得到结构体的大小
        int size = Marshal.SizeOf(structObj);

        //创建byte数组
        byte[] bytes = new byte[size];
        //分配结构体大小的内存空间
        IntPtr structPtr = Marshal.AllocHGlobal(size);

        //将结构体拷贝到分配的内存空间
        Marshal.StructureToPtr(structObj, structPtr, false);
        //从内存空间拷贝到byte数组
        Marshal.Copy(structPtr, bytes, 0, size);

        //释放内存空间
        Marshal.FreeHGlobal(structPtr);
        //返回byte数组
        return bytes;
    }


    /// <summary>
    /// byte数组转结构
    /// </summary>
    /// <param name="bytes">byte数组</param>
    /// <param name="type">结构类型</param>
    /// <returns>转换后的结构</returns>
    public static object BytesToStructFunc(byte[] bytes, Type type)
    {
        int size = Marshal.SizeOf(type);

        //byte数组长度小于结构的大小
        if (size > bytes.Length)
        {
            //返回空
            return null;
        }
        //分配结构大小的内存空间
        IntPtr structPtr = Marshal.AllocHGlobal(size);

        //将byte数组拷贝到分配好的内存空间
        Marshal.Copy(bytes, 0, structPtr, size);
        //将内存空间转换为目标结构
        object obj = Marshal.PtrToStructure(structPtr, type);

        //释放内存空间
        Marshal.FreeHGlobal(structPtr);
        //返回结构
        return obj;
    }
    #endregion
}

public class AttrForCsvColumnLabel : Attribute
{
    public string Title { get; set; }
}
相关推荐
阿伟*rui2 小时前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
XiaoLeisj4 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck4 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei4 小时前
java的类加载机制的学习
java·学习
逐·風5 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Yaml46 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~6 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616886 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7896 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
_oP_i6 小时前
Unity Addressables 系统处理 WebGL 打包本地资源的一种高效方式
unity·游戏引擎·webgl