使用C#实现将CSV文件内容装配成对象列表

 更新时间:2023年12月03日 08:50:26   作者:rjcql  
这篇文章主要为大家详细介绍了如何使用C#实现将CSV文件内容装配成对象列表,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

写在前面

CSV文件采用纯文本的存储形式,字段间以分隔符进行区分,行之间以换行符进行切换,既可以用文本编辑器打开也可以用Excel编辑,可读性非常好,在游戏开发领域经常将其作为数值配置文件使用。文本编辑器推荐EmEditor,轻巧而不失强大,策划们用的爱不释手。程序将配置反序列化后,装箱成对象列表,就可以随意访问和操作了。

代码实现过程可以直接File.ReadAllLine,然后再逐行按分隔符分割,也可以使用专门的类库来操作;本文直接用现成的轮子LumenWorks.Framework.IO类库,通过NuGet获取并安装。

代码实现

    public static class CsvHelper
    {
 
        public static List<T> GetDataList<T>(string csvFilePath) where T : class
        {
            var list = new List<T>();
            if (!File.Exists(csvFilePath))
            {
                return list;
            }
 
            var csvType = typeof(T);
            var content = File.ReadAllBytes(csvFilePath);
            using (var ms = new MemoryStream(content))
            using (var sr = new StreamReader(ms, Encoding.GetEncoding("UTF-8"), true))
            using (var tr = sr as TextReader)
            {
                var cr = new CsvReader(tr, true);
                var props = csvType.GetProperties();
                var heads = cr.GetFieldHeaders();
                while (cr.ReadNextRecord())
                {
                    try
                    {
                        object obj = Activator.CreateInstance(csvType);
                        foreach (var prop in props)
                        {
                            if (!heads.Contains(prop.Name))
                                continue;
 
                            string value = cr[prop.Name];
                            prop.SetValue(obj, GetDefaultValue(prop, value), null);
                        }
                        list.Add(obj as T);
                    }
                    catch (Exception ex)
                    {
                        // log here
                        continue;
                    }
                }
            }
            return list;
        }
 
        private static object GetDefaultValue(PropertyInfo prop, string value)
        {
            switch (prop.PropertyType.Name)
            {
                case "String":
                    return value.ToNormalString();
                case "Int32":
                    return value.ToInt32();
                case "Decimal":
                    return value.ToDecimal();
                case "Single":
                    return value.ToFloat();
                case "Boolean":
                    return value.ToBoolean();
                case "DateTime":
                    return value.ToDateTime();
                case "Double":
                    return value.ToDouble();
                default:
                    return null;
            }
        }
 
        #region 类型转换方法
 
        /// <summary>
        /// 对象类型转换为Int32
        /// </summary>
        public static int ToInt32(this object obj)
        {
            if (obj == null)
                return 0;
            try
            {
                Type type = obj.GetType();
                if (type == typeof(double) ||
                    type == typeof(float) ||
                    type == typeof(decimal))
                    return (int)obj;
 
                int tmp;
                if (int.TryParse(obj.ToString(), out tmp))
                    return tmp;
            }
            catch
            {
                return 0;
            }
 
            return 0;
        }
 
        /// <summary>
        /// String to int.
        /// </summary>
        public static int ToInt32(this string obj)
        {
            if (string.IsNullOrEmpty(obj))
                return 0;
            try
            {
                if (obj.Contains("."))
                    return (int)Convert.ToSingle(obj);
                int tmp;
                if (int.TryParse(obj, out tmp))
                    return tmp;
            }
            catch
            {
                return 0;
            }
 
            return 0;
        }
 
        /// <summary>
        /// Double To Int
        /// </summary>
        public static int ToInt32(this double value)
        {
            try
            {
                return (int)value;
            }
            catch
            {
                return 0;
            }
        }
 
        /// <summary>
        /// Float To Int
        /// </summary>
        public static int ToInt32(this float value)
        {
            try
            {
                return (int)value;
            }
            catch
            {
                return 0;
            }
        }
 
        /// <summary>
        /// 对象类型转换为Int32
        /// </summary>
        public static long ToInt64(this object obj)
        {
            if (obj == null)
                return 0;
            try
            {
                long tmp;
                if (long.TryParse(obj.ToString(), out tmp))
                    return tmp;
            }
            catch
            {
                return 0;
            }
 
            return 0;
        }
 
        /// <summary>
        /// 转换为字符串
        /// </summary>
        public static string ToNormalString(this object obj)
        {
            if (obj == null)
                return string.Empty;
            try
            {
                return Convert.ToString(obj);
            }
            catch
            {
                return string.Empty;
            }
        }
 
        /// <summary>
        /// 转换为日期
        /// </summary>
        public static DateTime ToDateTime(this object obj)
        {
            if (obj == null)
            {
                return Convert.ToDateTime("1970-01-01 00:00:00");
            }
            try
            {
                return Convert.ToDateTime(obj.ToString());
            }
            catch
            {
                return Convert.ToDateTime("1970-01-01 00:00:00");
            }
 
        }
 
        /// <summary>
        /// 转换为布尔型
        /// </summary>
        public static bool ToBoolean(this object obj)
        {
            if (obj != null)
            {
                string type = obj.GetType().Name;
                switch (type)
                {
                    case "String":
                        return (obj.ToString().ToLower() == "true" || obj.ToString() == "1");
                    case "Int32":
                        return ((int)obj) == 1;
                    case "Boolean":
                        return (bool)obj;
                    default:
                        return false;
                }
            }
 
            return false;
        }
 
        /// <summary>
        /// 转换为十进制数值
        /// </summary>
        public static Decimal ToDecimal(this object obj)
        {
            decimal result = 0M;
            if (obj == null)
            {
                return 0M;
            }
            switch (obj.GetType().Name)
            {
                case "Int32":
                    return decimal.Parse(obj.ToString());
 
                case "Int64":
                    return decimal.Parse(obj.ToString());
 
                case "Boolean":
                    if ((bool)obj)
                    {
                        return 1M;
                    }
                    return 0M;
            }
            var resultString = Regex.Replace(obj.ToString(), "[^0-9.]", "");
            result = resultString.Length == 0 ? 0M : decimal.Parse(resultString);
            if (obj.ToString().StartsWith("-"))
            {
                result *= -1M;
            }
            return result;
 
        }
 
        /// <summary>
        /// 转换为双精度.
        /// </summary>
        public static double ToDouble(this object obj)
        {
            double d;
            if (double.TryParse(Convert.ToString(obj), out d))
                return d;
            else
                return 0;
        }
 
        /// <summary>
        /// 转换为单精度.
        /// </summary>
        public static float ToFloat(this object value)
        {
            var v = value.ToNormalString();
            if (v == "")
            {
                return 0;
            }
            else
            {
                float result;
                if (float.TryParse(v, out result))
                {
                    return result;
                }
                else
                {
                    return 0;
                }
            }
        }
 
        /// <summary>
        /// 时间转换.
        /// </summary>
        public static DateTime ToDateTimeOrCurrent(this object obj)
        {
            DateTime dt;
            if (DateTime.TryParse(Convert.ToString(obj), out dt))
                return dt;
            else
                return DateTime.Now;
        }
         
        #endregion
    }

示例 CSV 文件内容:

Name,Age,IsMale,Birthday
Lee,28,TRUE,1996/1/1
Jane,29,FALSE,1997/11/1

示例 CSV 文件对应的反序列化目标类:

    public class TestConfig
    {
        public string Name { get; set; }
 
        public int Age { get; set; }
 
        public bool IsMale { get; set; }
 
        public DateTime Birthday { get; set; }
    }

调用示例

    var csvFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestConfigs.csv");
    var list = CsvHelper.GetDataList<TestConfig>(csvFilePath);
    foreach (var item in list)
    {
        var name = item.Name;
        var age = item.Age;
        var isMale = item.IsMale;
        var birthday = item.Birthday;
        var sex = isMale ? "male" : "female";
        Console.WriteLine($"{name} is {sex}");
    }

执行结果:

以上就是使用C#实现将CSV文件内容装配成对象列表的详细内容,更多关于C# CSV装配成对象列表的资料请关注脚本之家其它相关文章!

相关文章

  • C#获取属性的displayName的3种方式

    C#获取属性的displayName的3种方式

    在C#中,获取属性的displayName可以通过多种方式实现,包括使用特性、反射和LINQ,下面我将分别展示每种方法,并提供具体的示例代码,感兴趣的朋友可以参考下
    2024-07-07
  • C# 中如何取绝对值函数

    C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • C# AttributeUsage使用案例详解

    C# AttributeUsage使用案例详解

    这篇文章主要介绍了C# AttributeUsage使用案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C# XML文件操作之相机参数保存和读取

    C# XML文件操作之相机参数保存和读取

    XML是可扩展标记语言是一种数据语言,它将数据以一种简单的文本格式存储,可以被人类和几乎任何计算机理解。本文将利用C#实现相机参数读取并保存至XML文件,感兴趣的可以学习一下
    2022-11-11
  • 使用C#开发OPC Server服务器源码解析

    使用C#开发OPC Server服务器源码解析

    OPC Server服务器服务器的开发比较繁琐,本示例采用C#提供了一种简单快速实现OPCServer的方法,已经在工程项目中应用,本文对C#开发OPC Server服务器相关知识给大家介绍的非常详细,需要的朋友参考下吧
    2022-06-06
  • WPF应用启动慢的问题解决

    WPF应用启动慢的问题解决

    今天碰到一个奇怪的现象,在某些机器上,进行了系统还原后,WPF应用打开较慢,约有35s。本文先记录下该问题的解决方案,应用启动性能官方文档中有说明,还有搜到的其它方案没来得及测试,如NGEN update
    2021-05-05
  • C#基础之泛型

    C#基础之泛型

    泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能。接下来通过本文给大家介绍c#基础之泛型,感兴趣的朋友一起学习吧
    2016-08-08
  • C#计算矩阵的秩实例分析

    C#计算矩阵的秩实例分析

    这篇文章主要介绍了C#计算矩阵的秩实现方法,以实例形式较为详细的分析了C#计算矩阵秩的原理与实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • c#中task与thread区别及其使用的方法示例

    c#中task与thread区别及其使用的方法示例

    本文主要介绍了c#中task与thread区别及其使用的方法示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • C#6.0中你可能不知道的新特性总结

    C#6.0中你可能不知道的新特性总结

    C# 6 已经出来很久了,但最近发现真的有必要整理下,下面这篇文章主要给大家介绍了关于C#6.0中一些你可能不知道的新特性的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2018-04-04

最新评论