使用C#實(shí)現(xiàn)將CSV文件內(nèi)容裝配成對(duì)象列表
寫(xiě)在前面
CSV文件采用純文本的存儲(chǔ)形式,字段間以分隔符進(jìn)行區(qū)分,行之間以換行符進(jìn)行切換,既可以用文本編輯器打開(kāi)也可以用Excel編輯,可讀性非常好,在游戲開(kāi)發(fā)領(lǐng)域經(jīng)常將其作為數(shù)值配置文件使用。文本編輯器推薦EmEditor,輕巧而不失強(qiáng)大,策劃們用的愛(ài)不釋手。程序?qū)⑴渲梅葱蛄谢?,裝箱成對(duì)象列表,就可以隨意訪問(wèn)和操作了。
代碼實(shí)現(xiàn)過(guò)程可以直接File.ReadAllLine,然后再逐行按分隔符分割,也可以使用專(zhuān)門(mén)的類(lèi)庫(kù)來(lái)操作;本文直接用現(xiàn)成的輪子LumenWorks.Framework.IO類(lèi)庫(kù),通過(guò)NuGet獲取并安裝。
代碼實(shí)現(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 類(lèi)型轉(zhuǎn)換方法 /// <summary> /// 對(duì)象類(lèi)型轉(zhuǎn)換為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> /// 對(duì)象類(lèi)型轉(zhuǎn)換為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> /// 轉(zhuǎn)換為字符串 /// </summary> public static string ToNormalString(this object obj) { if (obj == null) return string.Empty; try { return Convert.ToString(obj); } catch { return string.Empty; } } /// <summary> /// 轉(zhuǎn)換為日期 /// </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> /// 轉(zhuǎn)換為布爾型 /// </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> /// 轉(zhuǎn)換為十進(jìn)制數(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> /// 轉(zhuǎn)換為雙精度. /// </summary> public static double ToDouble(this object obj) { double d; if (double.TryParse(Convert.ToString(obj), out d)) return d; else return 0; } /// <summary> /// 轉(zhuǎn)換為單精度. /// </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> /// 時(shí)間轉(zhuǎn)換. /// </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 文件內(nèi)容:
Name,Age,IsMale,Birthday
Lee,28,TRUE,1996/1/1
Jane,29,FALSE,1997/11/1
示例 CSV 文件對(duì)應(yīng)的反序列化目標(biāo)類(lèi):
public class TestConfig { public string Name { get; set; } public int Age { get; set; } public bool IsMale { get; set; } public DateTime Birthday { get; set; } }
調(diào)用示例
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í)行結(jié)果:
以上就是使用C#實(shí)現(xiàn)將CSV文件內(nèi)容裝配成對(duì)象列表的詳細(xì)內(nèi)容,更多關(guān)于C# CSV裝配成對(duì)象列表的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#編寫(xiě)Windows服務(wù)實(shí)例代碼
本篇文章主要介紹使用Microsoft Visual Studio2012可以很方便的創(chuàng)建一個(gè)Windows服務(wù),本例實(shí)現(xiàn)一個(gè)向D盤(pán)的txt文件里,寫(xiě)入系統(tǒng)時(shí)間的Windows服務(wù)2013-10-10c#中將uint值轉(zhuǎn)換成int的實(shí)例方法
在本文里小編給大家整理的是關(guān)于c#中將uint值轉(zhuǎn)換成int的實(shí)例方法,需要的朋友們學(xué)習(xí)參考下。2019-08-08總結(jié)C#刪除字符串?dāng)?shù)組中空字符串的幾種方法
C#中要如何才能刪除一個(gè)字符串?dāng)?shù)組中的空字符串呢?下面的文章會(huì)介紹多種方式來(lái)實(shí)現(xiàn)清除數(shù)組中的空字符串,以及在.net中將字符串?dāng)?shù)組中字符串為空的元素去除。2016-08-08C#反射在實(shí)際應(yīng)用中的實(shí)例代碼
C#反射在實(shí)際應(yīng)用中的實(shí)例代碼,需要的朋友可以參考一下2013-03-03C#中將UTC時(shí)間轉(zhuǎn)換為JST時(shí)間的實(shí)現(xiàn)方法
在C#中,將UTC時(shí)間轉(zhuǎn)換為JST(日本標(biāo)準(zhǔn)時(shí)間,即UTC+9)時(shí)間可以通過(guò)使用 DateTime 和 TimeZoneInfo 類(lèi)來(lái)實(shí)現(xiàn),JST比UTC快9小時(shí),因此可以直接進(jìn)行轉(zhuǎn)換,本文將通過(guò)代碼示例給大家介紹C#中將UTC時(shí)間轉(zhuǎn)換為JST時(shí)間,需要的朋友可以參考下2025-01-01C#對(duì)Task中的異常進(jìn)行捕獲的幾種常見(jiàn)方法
在C#中異步Task是一個(gè)很方便的語(yǔ)法,經(jīng)常用在處理異步,例如需要下載等待等方法中,不用函數(shù)跳轉(zhuǎn),代碼閱讀性大大提高,深受大家喜歡,但是有時(shí)候發(fā)現(xiàn)我們的異步函數(shù)可能出現(xiàn)了報(bào)錯(cuò),本文給大家介紹了C#對(duì)Task中的異常進(jìn)行捕獲的幾種常見(jiàn)方法,需要的朋友可以參考下2025-01-01解析如何使用反射調(diào)用類(lèi)型成員 方法,字段,屬性
本篇文章是對(duì)使用反射調(diào)用類(lèi)型成員 方法,字段,屬性進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06C#如何利用結(jié)構(gòu)體對(duì)固定格式數(shù)據(jù)進(jìn)行解析
這篇文章主要為大家詳細(xì)介紹了C#利用結(jié)構(gòu)體對(duì)固定格式數(shù)據(jù)進(jìn)行解析,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01C#實(shí)現(xiàn)按數(shù)據(jù)庫(kù)郵件列表發(fā)送郵件的方法
這篇文章主要介紹了C#實(shí)現(xiàn)按數(shù)據(jù)庫(kù)郵件列表發(fā)送郵件的方法,涉及C#讀取數(shù)據(jù)庫(kù)及通過(guò)自定義函數(shù)發(fā)送郵件的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07