技术频道导航
HTML/CSS
.NET技术
IIS技术
PHP技术
Js/JQuery
Photoshop
Fireworks
服务器技术
操作系统
网站运营

赞助商

分类目录

赞助商

最新文章

搜索

11示例教你用C# .NET CsvHelper读写CSV文件(1)

作者:admin    时间:2023-5-19 15:52:38    浏览:

C# .NET 使用 CsvHelper 读写CSV文件,是一个简单易用的值得推荐的方法,在前文中,我详细介绍了 CsvHelper 的特征、用法等知识,在本文中,将通过11个示例详细介绍如何使用 CsvHelper 读写CSV文件。

先决条件

以下是使用 CsvHelper 所需的一些先决条件,这些是使用 CsvHelper 时隐含的 .NET 基础知识。

使用和处置

每当你有一个对象实现IDisposable时,你需要在用完资源时释放它。大多数使用非托管资源的类都将实现IDisposable,这意味着System.IO命名空间中的许多类都需要被销毁。

处理完对象的最佳做法是将代码包装在一个using块中,当using块退出时,资源将尽快自动处理。

using (var stream = new MemoryStream())
{
    // Use the stream.
}
// The stream will be disposed of as soon as possible.

如果你需要保留它一段时间并在以后处理它,using为你做一些错误处理,所以使用它而不是Dispose直接调用仍然是个好主意。

var stream = new MemoryStream();
// Later in a different part of your code.
using (stream) { }

读写文件

要打开文件进行读取或写入,我们可以使用System.IO.File

using (var stream = File.OpenRead("path\\to\\file.csv"))
{
}

using (var stream = File.OpenWrite("path\\to\\file.csv"))
{
}

这些都返回一个FileStream用于处理我们的文件。由于我们的数据是文本,因此我们需要使用 StreamReaderStreamWriter 来读写文本。

using (var stream = File.OpenRead("path\\to\\file.csv"))
using (var reader = new StreamReader(stream))
{
}

using (var stream = File.OpenWrite("path\\to\\file.csv"))
using (var writer = new StreamWriter(stream))
{
}

StreamReaderStreamWriter有执行此操作的快捷方式。

using (var reader = new StreamReader("path\\to\\file.csv"))
{
}

using (var writer = new StreamWriter("path\\to\\file.csv"))
{
}

CsvHelper 对你的编码一无所知,因此如果你有特定的编码,则需要在流中指定它。

using (var reader = new StreamReader("path\\to\\file.csv", Encoding.UTF8))
{
}

using (var writer = new StreamWriter("path\\to\\file.csv", Encoding.UTF8))
{
}

CsvReaderCsvWriter 在他们的构造函数中使用 TextReaderTextWriterTextReaderTextWriter是阅读和写作文本的abstract类。StreamReader 继承 TextReader , StreamWriter 继承TextWriter,所以我们可以使用CsvReaderCsvWriter

using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader))
{
}

using (var writer = new StreamWriter("path\\to\\file.csv"))
using (var csv = new CsvWriter(writer))
{
}

Streams

从流中读取时,如果需要回到流的开头,可以使用 Stream.Position属性。

using (var stream = new File.OpenRead("path\\to\\file"))
using (var reader = new StreamReader(stream))
{
    // Read file content.
    var content = reader.ReadToEnd();

    // Go back to beginning of the stream.
    stream.Position = 0;

    // Read file content again.
    content = reader.ReadToEnd();
}

写入文件时,需要刷新写入器才能将数据写入流。StreamWriter 包含一个内部缓冲区,数据仅在缓冲区已满或被调用Flush时写入流。当using块退出时自动调用Flush

using (var stream = new File.OpenWrite("path\\to\\file"))
using (var writer = new StreamWriter(stream))
{
    writer.WriteLine("Foo");
    writer.Flush(); // Data is written from the writer buffer to the stream.
} // Flush is also called here.

读CSV文件[示例]

获得类记录

将 CSV 行转换为类对象。

数据

Id,Name
1,one

例子

void Main()
{
    using (var reader = new StreamReader("path\\to\\file.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var records = csv.GetRecords<Foo>();
    }
}

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

获取动态记录

将 CSV 行转换为动态对象。由于无法确定属性应该是什么类型,因此动态对象上的所有属性都是字符串。

数据

Id,Name
1,one

例子

void Main()
{
    using (var reader = new StreamReader("path\\to\\file.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var records = csv.GetRecords<dynamic>();
    }
}

获取匿名类型记录

将 CSV 行转换为匿名类型对象。你只需要提供匿名类型定义。

数据

Id,Name
1,one

例子

void Main()
{
    using (var reader = new StreamReader("path\\to\\file.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var anonymousTypeDefinition = new
        {
            Id = default(int),
            Name = string.Empty
        };
        var records = csv.GetRecords(anonymousTypeDefinition);
    }
}

枚举类记录

将 CSV 行转换为在可枚举的每次迭代中重复使用的类对象。每个枚举都会混合给定的记录,但仅限于映射的成员。如果你提供了一个映射但没有映射其中一个成员,则该成员将不会与当前行的数据混合。当心在强制IEnumerable评估的投影上调用的任何方法,例如ToList(),你将获得一个列表,其中所有记录都是你提供的与 CSV 文件中的最后一条记录混合的相同实例。

数据

Id,Name
1,one

例子

void Main()
{
    using (var reader = new StreamReader("path\\to\\file.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var record = new Foo();
        var records = csv.EnumerateRecords(record);
        foreach (var r in records)
        {
            // r is the same instance as record.
        }
    }
}

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

手动读取

有时出于各种原因,不尝试配置映射以匹配你的类定义会更容易。通常只需要多几行代码就可以手动读取行。

数据

Id,Name
1,one

例子

void Main()
{
    using (var reader = new StreamReader("path\\to\\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"),
                Name = csv.GetField("Name")
            };
            records.Add(record);
        }
    }
}

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

读取多个数据集

出于某种原因,存在包含多组 CSV 数据的 CSV 文件。你应该能够毫无问题地读取这样的文件。你将需要检测何时更改要检索的类类型。

数据

FooId,Name
1,foo

BarId,Name
07a0fca2-1b1c-4e44-b1be-c2b05da5afc7,bar

例子

void Main()
{
    var config = new CsvConfiguration(CultureInfo.InvariantCulture)
    {
        IgnoreBlankLines = false,
    };
    using (var reader = new StreamReader("path\\to\\file.csv"))
    using (var csv = new CsvReader(reader, config))
    {
        csv.Context.RegisterClassMap<FooMap>();
        csv.Context.RegisterClassMap<BarMap>();
        var fooRecords = new List<Foo>();
        var barRecords = new List<Bar>();
        var isHeader = true;
        while (csv.Read())
        {
            if (isHeader)
            {
                csv.ReadHeader();
                isHeader = false;
                continue;
            }
            
            if (string.IsNullOrEmpty(csv.GetField(0)))
            {
                isHeader = true;
                continue;
            }

            switch (csv.HeaderRecord[0])
            {
                case "FooId":
                    fooRecords.Add(csv.GetRecord<Foo>());
                    break;
                case "BarId":
                    barRecords.Add(csv.GetRecord<Bar>());
                    break;
                default:
                    throw new InvalidOperationException("Unknown record type.");
            }
        }
    }
}

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

public class Bar
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

public sealed class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
        Map(m => m.Id).Name("FooId");
        Map(m => m.Name);
    }
}

public sealed class BarMap : ClassMap<Bar>
{
    public BarMap()
    {
        Map(m => m.Id).Name("BarId");
        Map(m => m.Name);
    }
}

读取多种记录类型

如果你有 CSV 数据,其中每一行可能是不同的记录类型,你应该能够根据行类型或类似的东西读取。

数据

A,1,foo
B,07a0fca2-1b1c-4e44-b1be-c2b05da5afc7,bar

例子

void Main()
{
    var config = new CsvConfiguration(CultureInfo.InvariantCulture)
    {
        HasHeaderRecord = false,
    };
    using (var reader = new StreamReader("path\\to\\file.csv"))
    using (var csv = new CsvReader(reader, config))
    {
        csv.Context.RegisterClassMap<FooMap>();
        csv.Context.RegisterClassMap<BarMap>();
        var fooRecords = new List<Foo>();
        var barRecords = new List<Bar>();
        while (csv.Read())
        {
            switch (csv.GetField(0))
            {
                case "A":
                    fooRecords.Add(csv.GetRecord<Foo>());
                    break;
                case "B":
                    barRecords.Add(csv.GetRecord<Bar>());
                    break;
                default:
                    throw new InvalidOperationException("Unknown record type.");
            }
        }
    }
}

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

public class Bar
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

public sealed class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
        Map(m => m.Id).Index(1);
        Map(m => m.Name).Index(2);
    }
}

public sealed class BarMap : ClassMap<Bar>
{
    public BarMap()
    {
        Map(m => m.Id).Index(1);
        Map(m => m.Name).Index(2);
    }
}

写CSV文件[示例]

由于篇幅有限,CsvHelper 写CSV文件[示例]请参阅下一篇文章:

相关文章

标签: CSharp  CSV  CsvHelper  asp.net  
x
  • 站长推荐
/* 左侧显示文章内容目录 */