使用C#實現(xiàn)將CSV文件內容裝配成對象列表
寫在前面
CSV文件采用純文本的存儲形式,字段間以分隔符進行區(qū)分,行之間以換行符進行切換,既可以用文本編輯器打開也可以用Excel編輯,可讀性非常好,在游戲開發(fā)領域經常將其作為數(shù)值配置文件使用。文本編輯器推薦EmEditor,輕巧而不失強大,策劃們用的愛不釋手。程序將配置反序列化后,裝箱成對象列表,就可以隨意訪問和操作了。
代碼實現(xiàn)過程可以直接File.ReadAllLine,然后再逐行按分隔符分割,也可以使用專門的類庫來操作;本文直接用現(xiàn)成的輪子LumenWorks.Framework.IO類庫,通過NuGet獲取并安裝。
代碼實現(xiàn)
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> /// 轉換為十進制數(shù)值 /// </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}"); }
執(zhí)行結果:
以上就是使用C#實現(xiàn)將CSV文件內容裝配成對象列表的詳細內容,更多關于C# CSV裝配成對象列表的資料請關注腳本之家其它相關文章!
相關文章
C#實現(xiàn)按數(shù)據(jù)庫郵件列表發(fā)送郵件的方法
這篇文章主要介紹了C#實現(xiàn)按數(shù)據(jù)庫郵件列表發(fā)送郵件的方法,涉及C#讀取數(shù)據(jù)庫及通過自定義函數(shù)發(fā)送郵件的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07