TinyCsvParser - 使用C#解析CSV数据
作者:admin 时间:2023-5-19 23:50:41 浏览:关于使用C#解析、读写CSV数据,前面我已经介绍过几个方法,可参阅下面文章。
本文中,我将介绍另一个方法,那就是使用 TinyCsvParser , 一个CSV解析器。
TinyCsvParser 介绍
TinyCsvParser 是一个 .NET 库,用于以简单的方式解析 CSV 数据,同时提供非常高性能和非常干净的 API。它是高度可配置的,以提供最大的灵活性。
TinyCsvParser 支持 .NET Core。
我们可以在 github 查看 TinyCsvParser 的最新信息、使用说明及发行版本,并下载它:
https://github.com/bytefish/TinyCsvParser
我们还可以使用 NuGet 包。要安装 TinyCsvParser ,请在程序包管理器控制台中运行以下命令。
PM> Install-Package TinyCsvParser
基本用法
想象一下,我们在 CSV 文件中有一个人的列表,其中包含他们的名字、姓氏和生日。
Philipp;Wagner;1986/05/12
Max;Musterman;2014/01/02
我们系统中相应的域模型可能如下所示。
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
}
使用TinyCsvParser时,必须定义 CSV 数据中的列与域模型中的属性之间的映射。
public class CsvPersonMapping : CsvMapping<Person>
{
public CsvPersonMapping()
: base()
{
MapProperty(0, x => x.FirstName);
MapProperty(1, x => x.LastName);
MapProperty(2, x => x.BirthDate);
}
}
然后我们可以通过CsvParser
使用映射来解析。
namespace TinyCsvParser.Test
{
[TestFixture]
public class TinyCsvParserTest
{
[Test]
public void TinyCsvTest()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, new[] { ';' });
CsvReaderOptions csvReaderOptions = new CsvReaderOptions(new[] { Environment.NewLine });
CsvPersonMapping csvMapper = new CsvPersonMapping();
CsvParser<Person> csvParser = new CsvParser<Person>(csvParserOptions, csvMapper);
var stringBuilder = new StringBuilder()
.AppendLine("FirstName;LastName;BirthDate")
.AppendLine("Philipp;Wagner;1986/05/12")
.AppendLine("Max;Mustermann;2014/01/01");
var result = csvParser
.ReadFromString(csvReaderOptions, stringBuilder.ToString())
.ToList();
Assert.AreEqual(2, result.Count);
Assert.IsTrue(result.All(x => x.IsValid));
// Asserts ...
}
}
}
就是这样!示例中的CsvParserOptions
设置为跳过标题,使用\n
为行分隔符和;
为列分隔符。
高级用法
自定义类型转换器
现在想象一下,你的客户突然将一个人的生日更改为一种奇怪的格式,并像这样写日期2004###01###25。我们无法使用默认转换器解析此类日期格式,但在TinyCsvParser中,我们可以轻松定义DateTimeConverter
具有自定义日期时间格式。
映射属性时,你可以使用WithCustomConverter
方法覆盖默认转换器。我们用给定的格式yyyy###MM###dd实例化DateTimeConverter
。
private class CsvPersonMappingWithCustomConverter : CsvMapping<Person>
{
public CsvPersonMappingWithCustomConverter()
{
MapProperty(0, x => x.FirstName);
MapProperty(1, x => x.LastName);
MapProperty(2, x => x.BirthDate)
.WithCustomConverter(new DateTimeConverter("yyyy###MM###dd"));
}
}
然后让我们编写一个单元测试来验证预期的结果。
[Test]
public void WeirdDateTimeTest_CustomConverterBased()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, new[] { ';' });
CsvReaderOptions csvReaderOptions = new CsvReaderOptions(new[] { Environment.NewLine });
CsvPersonMappingWithCustomConverter csvMapper = new CsvPersonMappingWithCustomConverter();
CsvParser<Person> csvParser = new CsvParser<Person>(csvParserOptions, csvMapper);
var stringBuilder = new StringBuilder()
.AppendLine("FirstName;LastName;BirthDate")
.AppendLine("Philipp;Wagner;1986###05###12");
var result = csvParser
.ReadFromString(csvReaderOptions, stringBuilder.ToString())
.ToList();
Assert.AreEqual("Philipp", result[0].Result.FirstName);
Assert.AreEqual("Wagner", result[0].Result.LastName);
Assert.AreEqual(1986, result[0].Result.BirthDate.Year);
Assert.AreEqual(5, result[0].Result.BirthDate.Month);
Assert.AreEqual(12, result[0].Result.BirthDate.Day);
}
就是这样!
使用 PLINQ 发挥作用
解析器返回一个ParallelQuery,可用于对数据执行其他处理。我认为 LINQ 是 C# 中最神奇的东西之一!我能够在根本不处理锁或线程的情况下并行化整个解析。
在这个例子中,我们将解析数据并搜索所有 first name 含有Philipp
的名字 。看看我们如何根本不需要编写 if
语句?
[Test]
public void ParallelLinqTest()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, new[] { ';' });
CsvReaderOptions csvReaderOptions = new CsvReaderOptions(new[] { Environment.NewLine });
CsvPersonMapping csvMapper = new CsvPersonMapping();
CsvParser<Person> csvParser = new CsvParser<Person>(csvParserOptions, csvMapper);
var stringBuilder = new StringBuilder()
.AppendLine("FirstName;LastName;BirthDate")
.AppendLine("Philipp;Wagner;1986/05/12")
.AppendLine("Max;Mustermann;2014/01/01");
var result = csvParser
.ReadFromString(csvReaderOptions, stringBuilder.ToString())
.Where(x => x.IsValid)
.Where(x => x.Result.FirstName == "Philipp")
.ToList();
Assert.AreEqual(1, result.Count);
Assert.AreEqual("Philipp", result[0].Result.FirstName);
Assert.AreEqual("Wagner", result[0].Result.LastName);
Assert.AreEqual(1986, result[0].Result.BirthDate.Year);
Assert.AreEqual(5, result[0].Result.BirthDate.Month);
Assert.AreEqual(12, result[0].Result.BirthDate.Day);
}
总结
本文介绍了一个解析CSV数据的方法——TinyCsvParser,它在 C# 中构建了一个干净、易于使用且高性能的 CSV 解析库。
有关解析CSV的方法,我曾介绍过其他一些,你可参阅以下文章:
- 站长推荐