csv文件作为一种excel可以读写的文件,方便使用,且格式为分隔符类型的文件,任何程序都可以很方便的读写其中的数据,可以作为不同系统间简单的非实时的数据接口交互方式。

实际上,我们自己在写程序的时候也会写自己的工具库,不过,自己的用起来不如第三方很多人开发维护的,所以,给团队中其他同事,尤其是新人而言,这类工具会更高效。

C#中本身的标准库中好像没有csv相关工具,这里使用了第三方库CsvHelper。通过如下方式安装

根据官网实例如下:

实例1 读取文件直接转为类对象

这个是个比较实际的例子,假设文件名file.csv,其中数据格式为如下

Id Name
1 One
2 Two

我们新建一个数据类:

public class Foo
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }

然后就可以直接通过如下代码读取csv文件数据了,csv文件中的列名需要和类的属性名相同。

private void button1_Click(object sender, EventArgs e)
        {
            using (var reader = new StreamReader("file.csv"))
            using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
            {
                csv.Configuration.HasHeaderRecord = true;
                csv.Configuration.Delimiter = ",";
                var records = csv.GetRecords<Foo>(); //一次性读取所有数据,并且转换为对象集合。
                
                foreach (Foo line in records)
                {
                    Console.WriteLine($"{line.Id} {line.Name}");
                }
            }
        }

实例2 读取文件按字段提取

这个适用于比较灵活的方式,比如一个csv中有许多字段,但是我只需要其中某几个字段而已。

private void button3_Click(object sender, EventArgs e)
        {
            using (var reader = new StreamReader("file.csv"))
            using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
            {
                var records = new List<Foo>();
                csv.Read();//开始读取文件
                csv.ReadHeader();  //读取首行记录作为表头
                while (csv.Read())  //逐行读取
                {
                    var record = new Foo
                    {
                        Id = csv.GetField<int>("Id"),  //读取Id列
                        Name = csv.GetField("Name")   //读取Name列
                    };
                    records.Add(record);
                }

                foreach (Foo line in records)
                {
                    Console.WriteLine($"{line.Id} {line.Name}");
                }
            }
        }

实例3 读取文件到DataTable

这个应该是在UI开发中经常用到的,利用DataTable和Datagridview控件绑定可以很容易修改和现实数据。 但是csvHelper有个不足的地方,没有提供DataTable到csv文件的方法。 通过csvhelper读取的datatable对象绑定到Datagridview控件之后,只能显示,不能修改。 所以,如果需要修改,我这里采用的重新自定义了一个datatable对象的方式。

 private DataTable dt_new = new DataTable();
        private void button4_Click(object sender, EventArgs e)
        {
            using (var reader = new StreamReader("file.csv"))
            using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
            {
                // Do any configuration to `CsvReader` before creating CsvDataReader.
                using (var dr = new CsvDataReader(csv))
                {
                    dt_new.Columns.Clear();
                    var dt = new DataTable();
                    dt.Load(dr);
                    
                    //如果想实现datagridview修改同步到datatable,需要重新生成一个datatable对象,不能直接使用csv初始化
                    foreach (DataColumn col in dt.Columns)
                    {
                        dt_new.Columns.Add(col.ColumnName, col.DataType);
                    }
                    foreach (DataRow row in dt.Rows)
                    {
                        dt_new.Rows.Add(row["Id"],row["Name"]);
                    }
                    dt_new.TableName = "ddd";


                    dataGridView1.DataSource = dt_new;
                    Console.WriteLine(dataGridView1.Columns.IsReadOnly);
                }
            }
        }

实例4 写入对象集合到文件

使用类对象的集合数据写入

 var records = new List<Foo>
            {
                new Foo { Id = 1, Name = "one" },
            };

            using (var writer = new StreamWriter("file.csv",false))  //覆盖方式写入
            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                csv.WriteRecords(records);
            }

实例5 写入DataTable到文件

这个可以配合实例3,从而方便的读取和写入到csv文件,又很好的使用客户端UI界面进行更新等操作。

   var records = new List<Foo>();
            DataTable dt = dataGridView1.DataSource as DataTable;

            foreach (DataRow row in dt.Rows)
            {
                Foo foo = new Foo();
                foo.Id = Int32.Parse(row["Id"].ToString());
                foo.Name = row["Name"].ToString();
                records.Add(foo);
            }

            using (var writer = new StreamWriter("file.csv", false))
            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                csv.WriteRecords(records);
            }