使用C#實現(xiàn)將CSV文件內(nèi)容裝配成對象列表
寫在前面
CSV文件采用純文本的存儲形式,字段間以分隔符進行區(qū)分,行之間以換行符進行切換,既可以用文本編輯器打開也可以用Excel編輯,可讀性非常好,在游戲開發(fā)領(lǐng)域經(jīng)常將其作為數(shù)值配置文件使用。文本編輯器推薦EmEditor,輕巧而不失強大,策劃們用的愛不釋手。程序?qū)⑴渲梅葱蛄谢?,裝箱成對象列表,就可以隨意訪問和操作了。
代碼實現(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 類型轉(zhuǎn)換方法
/// <summary>
/// 對象類型轉(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>
/// 對象類型轉(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)換為十進制數(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>
/// 時間轉(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 文件對應(yīng)的反序列化目標類:
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#實現(xiàn)將CSV文件內(nèi)容裝配成對象列表的詳細內(nèi)容,更多關(guān)于C# CSV裝配成對象列表的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
總結(jié)C#刪除字符串數(shù)組中空字符串的幾種方法
C#中要如何才能刪除一個字符串數(shù)組中的空字符串呢?下面的文章會介紹多種方式來實現(xiàn)清除數(shù)組中的空字符串,以及在.net中將字符串數(shù)組中字符串為空的元素去除。2016-08-08
C#中將UTC時間轉(zhuǎn)換為JST時間的實現(xiàn)方法
在C#中,將UTC時間轉(zhuǎn)換為JST(日本標準時間,即UTC+9)時間可以通過使用 DateTime 和 TimeZoneInfo 類來實現(xiàn),JST比UTC快9小時,因此可以直接進行轉(zhuǎn)換,本文將通過代碼示例給大家介紹C#中將UTC時間轉(zhuǎn)換為JST時間,需要的朋友可以參考下2025-01-01
C#如何利用結(jié)構(gòu)體對固定格式數(shù)據(jù)進行解析
這篇文章主要為大家詳細介紹了C#利用結(jié)構(gòu)體對固定格式數(shù)據(jù)進行解析,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01
C#實現(xiàn)按數(shù)據(jù)庫郵件列表發(fā)送郵件的方法
這篇文章主要介紹了C#實現(xiàn)按數(shù)據(jù)庫郵件列表發(fā)送郵件的方法,涉及C#讀取數(shù)據(jù)庫及通過自定義函數(shù)發(fā)送郵件的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07

