C#实现导入CSV数据到List<T>的完整教程
在C#应用程序开发中,经常需要从CSV文件中导入数据并转换为对象列表。本文将详细介绍如何使用C#实现将CSV数据导入到List<T>
集合中。
一、功能概述
本实现主要包含以下功能:
通过文件对话框选择CSV文件
读取CSV文件内容到DataTable
处理不同编码格式的CSV文件
将DataTable数据转换为强类型对象列表
支持多种数据类型的自动转换
二、核心代码实现
1. 文件选择与导入事件处理
private void TsbImport_Click(object sender, EventArgs e) { try { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "CSV文件(*.csv)|*.csv|Excel97-2003 (*.xls)|*.xls"; ofd.ValidateNames = true; ofd.CheckPathExists = true; ofd.CheckFileExists = false; if (ofd.ShowDialog() == DialogResult.OK) { int success = 0; int error = 0; // 读取CSV文件到DataTable DataTable dataTable = FilePathToDataTable(ofd.FileName, 1); // 将DataTable转换为对象列表 List<tb_xxx> partsList = DataTableToList<tb_xxx>(dataTable, dicDgvType); // 处理导入的数据... } } catch (Exception ex) { // 异常处理 MessageBox.Show($"导入失败: {ex.Message}"); } }
2. CSV文件读取方法
public static DataTable FilePathToDataTable(string filePath, int n = 1) { FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); // 处理不同编码格式 load: StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8, false); Encoding encoding = Encoding.UTF8; DataTable dt = new DataTable(); try { int i = 0, m = 0; reader.Peek(); while (reader.Peek() > 0) { m = m + 1; string str = reader.ReadLine(); // 检测并处理乱码 if (str.Contains("�") || str.Contains("★") || str.Contains("╀") || str.Contains("??")) { // 尝试不同编码 switch (encoding.WebName) { case "utf-8": encoding = Encoding.Default; break; case "GB2312": encoding = Encoding.ASCII; break; case "us-ascii": encoding = Encoding.UTF7; break; case "utf-7": encoding = Encoding.Unicode; break; default: throw new Exception("文件内容乱码"); } goto load; } string[] split = str.Split(','); // 处理列标题 if (m < n + 1) { for (i = 0; i < split.Length; i++) { dt.Columns.Add(split[i]); } } else // 处理数据行 { DataRow dr = dt.NewRow(); for (i = 0; i < split.Length; i++) { dr[i] = split[i]; } dt.Rows.Add(dr); } } } catch (Exception ex) { dt = new DataTable(); } finally { stream.Close(); reader.Close(); } return dt; }
3. DataTable到List<T>的转换
public static List<T> DataTableToList<T>(DataTable dt, Dictionary<string, object> dicWhere) where T : new() { List<T> listCollection = new List<T>(dt.Rows.Count); if (dt == null || dt.Rows.Count <= 0) return listCollection; // 获取T类型的属性信息 PropertyInfo[] propertyInfoArray = typeof(T).GetProperties(); string tempName = string.Empty; // 遍历DataTable的每一行 foreach (DataRow dataRow in dt.Rows) { T t = new T(); // 遍历T类型的每个属性 foreach (PropertyInfo propertyInfo in propertyInfoArray) { tempName = propertyInfo.Name; tempName = dicWhere.Keys.Contains(tempName) ? dicWhere[tempName].ToString() : ""; if (dt.Columns.Contains(tempName)) { if (!propertyInfo.CanWrite) continue; try { object value = dataRow[tempName]; Type type = propertyInfo.PropertyType; if (value != DBNull.Value) { // 处理不同类型的数据转换 if (value.GetType() == type) { propertyInfo.SetValue(t, value, null); } else { // 处理各种数据类型的转换 // 包括byte、short、int、long、decimal、double、float、DateTime、bool等 // 详细代码见原始实现 } } } catch (Exception ex) { // 异常处理 } } } listCollection.Add(t); } return listCollection; }
三、使用示例
假设我们有一个tb_xxx
类:
public class tb_xxx { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } public DateTime CreateDate { get; set; } }
使用字段映射字典:
Dictionary<string, object> dicDgvType = new Dictionary<string, object> { {"Id", "编号"}, {"Name", "名称"}, {"Price", "价格"}, {"CreateDate", "创建日期"} };
四、注意事项
编码处理:CSV文件可能存在多种编码格式,代码中实现了自动检测和转换机制
数据类型转换:提供了丰富的数据类型转换支持,包括可空类型
异常处理:在各个关键步骤添加了异常处理,提高程序稳定性
性能优化:使用泛型和反射提高代码的复用性和灵活性
五、总结
本文介绍了如何使用C#将CSV文件数据导入到List<T>
集合中的完整实现。通过文件对话框选择文件、读取CSV内容、处理编码问题、数据类型转换等步骤,实现了灵活高效的数据导入功能。开发者可以根据实际需求调整和扩展此代码,以适应不同的业务场景。
此实现具有良好的可扩展性和健壮性,可以作为数据导入功能的基础框架,应用于各种C#应用程序中。