说说CSV文件和C#解析csv文件的几种方式

1.什么是csv文件?

CSV是一种通用的、相对简单的文件格式,具有以下特征:

  1. 1纯文本 ,使用某个字符集,比如ASCIIUnicodeEBCDICGB2312
  2. 2由记录组成(典型的是每行一条记录);
  3. 3.每条记录被分隔符分隔为字段(典型分隔符有逗号、分号或制表符;有时分隔符可以包括可选的空格);
  4. 4.每条记录都有同样的字段序列。

下面是一个实际 CSV 文件,让大家有一个感性的认识。我们选的是 Sjojo_Rescan 的 CSV 文件 (Sjojo 是 ASW- 亚洲扫图风的成员之一)。

FileName,ByeCount,CRC,

sj_mino1001.jpg,715282,4FB55FE8,

sj_mino1002.jpg,471289,93203C5C,

sj_mino1003.jpg,451929,C4E80467,

这个csv文件中,有3行记录,每个记录有3个字段,字段名分别分:FileName,ByeCount,CRC所有字段都是字符型!

好了,大概了解了csv之后,我们就看看如何解析读取csv文件记录和字段内容。

C# CSVhelper库,有CSVReader和CSVWriter类,分别用来读取和写入CSV内容,今天我们先讨论用CSVReader类来读取CSV文件内容。

一.将CSV文件所有行和字段逐行性全部读进来,

1.将csv文件以recource文件的形式加入到VS项目代码中,如下:

cs 复制代码
        /// <summary>
        ///   Looks up a localized string similar to ModelName,ThermalModel,PDCSV,IMSAssemblyNumber,ModelType,
        ///AC F2-A 24-280-001,F2A_24V_IPB014N06N_NE222_KDP153.mat,AC F2-A 24-280-001.csv,470672420,1,
        ///AC F2-A 24-280-001,OnSemi,AC F2-A 24-280-001 PDC-2038.csv,470672421,1,F2-A_24V_FDB0170N607L_NE236
        ///AC F2-A 48-240-001,F2A_48V_FDB1D7N10CL7_NE249_KDP89.mat,AC F2-A 48-240-001 PDC-10001.csv,470674820,1,
        ///AC F2-A 48-240-001,F2A_48V_IPB017N10N5_NE248_KDP82.mat,AC F2-A 48-240-001 PDC-2011.csv,470674821,1,
        ///AC F2-A 48-240-051,F2A_48V_FDB1D7N10CL7_NE249_KDP89.mat,AC [rest of string was truncated]&quot;;.
        /// </summary>
        internal static string model_release {
            get {
                return ResourceManager.GetString("model_release", resourceCulture);
            }
        }

        /// <summary>
        ///   Looks up a localized string similar to VariableName,AddressCAN,DataType,MemoryArea,FactoryDefault,FeatureArea,Release
        ///Cal_KSI,0x4F2500,UINT16,NV_PRODUCT,2001,Calibrations,2.1.0.8
        ///CAN_ConfigLock,0x319601,UINT8,NV_BOOT,0,CAN,2.3.0.0
        ///CAN_2_ConfigLock,0x319602,UINT8,NV_BOOT,0,CAN,2.3.0.0
        ///canopen_mandatory_hardware_version,0x100900,STRING,NV_STRINGS,FSERIES_PRIMARY.1.0,IO.Config,2.1.0.8
        ///CAN_Open_Product_Code,0x101802,INT32,NV_PRODUCT,0x0005F4D2,CAN,2.1.0.8
        ///CAN_Node_Id,0x200001,UINT16,NV_BOOT,0x0026,CAN,2.1.0.8
        ///CAN_2_Node_Id,0x200002,UINT16,NV_ [rest of string was truncated]&quot;;.
        /// </summary>
        internal static string _params {
            get {
                return ResourceManager.GetString("_params", resourceCulture);
            }
        }

2.Main方法中代码读取

cs 复制代码
        static void Main(string[] args)
        {
            using (TextReader tr = new StringReader(Resource.model_map_release))
            {
                using (CsvReader csv = new CsvReader(tr))
                {

                    //读取第一行表头
                    //ModelName,ThermalModel,PDCSV,IMSAssemblyNumber,ModelType,
                    //GetField 方法依赖于 CSV 文件的标题行(第一行),它需要先调用 csv.Read() 和 csv.ReadHeader() 方法来读取并解析标题行。
                    //如果跳过了标题行或没有调用 ReadHeader(),则无法通过列名获取字段。
                    csv.Read();
                    csv.ReadHeader();
                    string modelName = csv.GetField("ModelName");
                    string ThermalModel = csv.GetField(1);
                    string PDCSV = csv.GetField(2);
                    string IMSAssemblyNumber = csv.GetField(3);
                    string ModelType = csv.GetField(4);

                    //按行循环读取csv数据区域内容,直到read方法返回false即读取结束
                    int rowcount = 0;
                    while (csv.Read())
                    {
                        //获取当前行的field0内容
                        string field0 = csv.GetField("ModelName");

                        //获取当前行的field2内容
                        string field1 = csv.GetField("ThermalModel");

                        //获取当前行的field2内容
                        string field2 = csv.GetField("PDCSV");

                        //获取当前行的field Index = 3 的字段内容,并转换成整数
                        var field3 = csv.GetField<int>(3);

                        //获取当前行的field name = "IMSAssemblyNumber"的字段内容,并转换成整数
                        var field3_IMSAssemblyNumber = csv.GetField<int>("IMSAssemblyNumber");

                        //获取当前行的field4内容
                        string field4 = csv.GetField(4);

                        rowcount++;
                    }
                }
            }

以上是将csv文件中的内容全部读出来,想要处理或筛选部分内容就不是很方便,接下来我们用一些高级的方法定义读取csv的字段映射,以及用LINQ筛选出我们想要的数据.demo如下

首先建立一个类ThermalModel,定义需要的属性,用来对应csv文件中的字段,建立csvmodel字段和query类型属性的映射关系;csv中不需要获取的字段可以在类中不添加对应的属性,比如ThermalModel列,代码如下:

cs 复制代码
public class ThermalModelMap : ClassMap<ThermalModel>
    {
        public ThermalModelMap()
        {
            Map(m => m.ModelName);
            Map(m => m.PDCSV);
            Map(m => m.IMSAssemblyNumber);
            Map(m => m.ModelType);
        }
    } 

    public class ThermalModel
    {
        /// <summary>
        /// Gets or sets the model name of the thermal model
        /// </summary>
        public string ModelName { get; set; }

        /// <summary>
        /// Gets or sets the product model (thermal model PD file)
        /// </summary>
        public string PDCSV { get; set; }

        /// <summary>
        /// Gets or sets the IMS board part number
        /// </summary>
        public string IMSAssemblyNumber { get; set; }

        public string ModelType { get; set; }
    }
cs 复制代码
static void Main(string[] args)
        {
            //获取csv文件中的内容
            string modelsContext = Resource.ResourceManager.GetObject("model_map_release").ToString();

            //将csv内容转成TextReader对象
            using (TextReader reader = new StringReader(modelsContext))
            {
                using (CsvReader csv = new CsvReader(reader))
                {
                    //建立类型的属性与csv文件字段映射注册关系,取4个字段,去掉CSV中不需要的ThermalModel列
                    csv.Configuration.RegisterClassMap<ThermalModelMap>();

                    //将csv中的数据一次性全部读出来,转成泛型集合对象
                    var modellist = csv.GetRecords<ThermalModel>().ToList();

                    //筛选需要的内容
                    var modeldNeed = modellist.Where(m => int.Parse(m.ModelType) == 1);
                }
            }
        }

ClassMap<T>类与CSV文件字段可以建立复杂的映射关系,类中定义的属性与CSV字段都有一一对应的关系,如果类中某个属性不用了,可以在建立映射关系时,用Ignore方法不建议该映射关系。如下:

cs 复制代码
public sealed class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        //类的ID属性,映射到CSV的ProductID列
        Map(m => m.Id).Name("ProductID");
        
        //类的Name属性,映射到CSV的ProductName列
        Map(m => m.Name).Name("ProductName");

        // 将CSV "Price" 列的值转换为 decimal,并移除货币符号
        Map(m => m.Price).ConvertUsing(row => decimal.Parse(row.GetField<string>("Price").Replace("$", "")));

        // 忽略 "CreatedAt" 属性
        Map(m => m.CreatedAt).Ignore();
    }
}

public class Product
{
    public string ProductName { get; set; }
    public int ProductID { get; set; }
    public string CreatedAt { get; set; }
}

注册时机 ‌:RegisterClassMap 必须在调用 GetRecords<T>()WriteRecords() 之前完成。

配置作用域 ‌:RegisterClassMap 作用于当前的 CsvReaderCsvWriter 实例的配置。

相关推荐
m0_462605222 小时前
第G3周:CGAN入门|生成手势图像
人工智能
bubiyoushang8882 小时前
基于LSTM神经网络的短期风速预测实现方案
人工智能·神经网络·lstm
中烟创新2 小时前
烟草专卖文书生成智能体与法规案卷评查智能体获评“年度技术最佳实践奖”
人工智能
得一录2 小时前
大模型中的多模态知识
人工智能·aigc
Github掘金计划3 小时前
Claude Work 开源平替来了:让 AI 代理从“终端命令“变成“产品体验“
人工智能·开源
ghgxm5203 小时前
Fastapi_00_学习方向 ——无编程基础如何用AI实现APP生成
人工智能·学习·fastapi
LongtengGensSupreme3 小时前
C# 中监听 IPv6 回环地址----HttpListener
c#·ipv6·httplistener
余俊晖3 小时前
3秒实现语音克隆的Qwen3-TTS的Qwen-TTS-Tokenizer和方法架构概览
人工智能·语音识别
森屿~~3 小时前
AI 手势识别系统:踩坑与实现全记录 (PyTorch + MediaPipe)
人工智能·pytorch·python