C#实现导入CSV数据到List<T>的完整教程

发布于:2025-09-07 ⋅ 阅读:(20) ⋅ 点赞:(0)

C#实现导入CSV数据到List<T>的完整教程

在C#应用程序开发中,经常需要从CSV文件中导入数据并转换为对象列表。本文将详细介绍如何使用C#实现将CSV数据导入到List<T>集合中。

一、功能概述

本实现主要包含以下功能:

  1. 通过文件对话框选择CSV文件

  2. 读取CSV文件内容到DataTable

  3. 处理不同编码格式的CSV文件

  4. 将DataTable数据转换为强类型对象列表

  5. 支持多种数据类型的自动转换

二、核心代码实现

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", "创建日期"}
};

四、注意事项

  1. 编码处理:CSV文件可能存在多种编码格式,代码中实现了自动检测和转换机制

  2. 数据类型转换:提供了丰富的数据类型转换支持,包括可空类型

  3. 异常处理:在各个关键步骤添加了异常处理,提高程序稳定性

  4. 性能优化:使用泛型和反射提高代码的复用性和灵活性

五、总结

本文介绍了如何使用C#将CSV文件数据导入到List<T>集合中的完整实现。通过文件对话框选择文件、读取CSV内容、处理编码问题、数据类型转换等步骤,实现了灵活高效的数据导入功能。开发者可以根据实际需求调整和扩展此代码,以适应不同的业务场景。

此实现具有良好的可扩展性和健壮性,可以作为数据导入功能的基础框架,应用于各种C#应用程序中。


网站公告

今日签到

点亮在社区的每一天
去签到