使用C#实现将CSV文件内容装配成对象列表
作者: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装配成对象列表的资料请关注脚本之家其它相关文章!