感谢

本篇首先特别感谢从此启程兄的《.NetCore外国一些高质量博客分享》, 发现很多国外的.NET Core技术博客资源, 我会不定期从中选择一些有意思的文章翻译总结一下。

.NET Core中的CSV解析库

本篇博客来源于.NET Core Totorials的《CSV Parsing In .NET Core》

背景介绍

对于初级程序员来说, 使用string.Split(',')来解析CSV文件基本就是唯一可行的方法, 但是之后他们会发现除了使用逗号分隔值之外,CSV中还有其他需要处理的东西,所以作者就介绍了CSV解析的一些痛点并推荐了2个比较好用CSV解析库。

CSV解析一些痛点

  • 一个CSV文件有可能有表头,也可能没有表头。如果表头存在的话,解析CSV时,列的顺序就不太重要了,因为你可以根据表头知道所需的数据在第几列。如果表头不存在的话,解析CSV时,就需要依赖列的顺序。所以CSV的解析,应该即支持表头,也支持按列的顺序。
  • CSV文件中某一列的值可能是带双引号的字符串,字符串中可能包含换行符、逗号,双引号。
    • 例1:1,2,"a,b"
    • 例2: 1,2,"a[换行符]b"
    • 例3: 1,2,"this is ""Good""." (注:双引号字符串中的出现的连续双引号表示转义,这里真正的文本是this is "Good".)
  • CSV文件中每一行的数据的数据列数量“应该”一样,但不是必须一样,所以解析CSV需要处理这些不一致的情况
  • 在.NET中,当反序列化一个CSV文件的时候,还需要
    • 支持反序列化成集合
    • 支持枚举
    • 支持自定义映射
    • 支持映射嵌套对象

.NET Core中的一些优秀CSV解析库

这里作者推荐了2个CSV解析库,一个是CSVHelper, 一个是Tiny CSV Parser。

测试例子

为了测试这些CSV解析库,我们首先创建一个.NET Core的控制台程序

然后我们添加一个Automobile类,其代码如下

    public class Automobile
{
public string Make { get; set; }
public string Model { get; set; }
public AutomobileType Type { get; set; }
public int Year { get; set; }
public decimal Price { get; set; }
public AutomobileComment Comment { get; set; } public override string ToString()
{
StringBuilder builder = new StringBuilder();
builder.AppendLine();
builder.AppendLine($"Make: {Make}");
builder.AppendLine($"Model: {Model}");
builder.AppendLine($"Type: {Type.ToString()}");
builder.AppendLine($"Year: {Year}");
builder.AppendLine($"Price: {Price}");
builder.AppendLine($"Comment: {Comment?.Comment}"); return builder.ToString();
}
} public class AutomobileComment
{
public string Comment { get; set; }
} public enum AutomobileType
{
None,
Car,
Truck,
Motorbike
}

最后我们创建一个csv文件sample.txt作为测试文件,我们希望将当前csv文件中的数据,反序列化到一个Automobile类的对象实例中。

其内容如下

Make,Model,Type,Year,Price,Comment
"Toyota",Corolla,Car,1990,2000.99,"Comment with a,
line break and "" quotes"

这个文件中第一行是一个表头,第二行是一个数据行,数据行中包含了

  • 字符串内容换行
  • 字符串中有逗号
  • 字符串中有双引号

CSVHelper

CSVHelper是一个CSV文件的读写库。它支持读写自定义类对象。官网地址https://joshclose.github.io/CsvHelper/

安装

我们可以使用Package Manager Console来安装CSVHelper。

命令如下:

PM> Install-Package CsvHelper

解析CSV

使用CSVHelper解析CSV文件代码很简单, 还需要2步

  • 使用CsvReader类的对象实例读取CSV文件
  • 使用GetRecords方法来反序列化
    using (TextReader reader = new StreamReader("sample.txt"))
{
var csvReader = new CsvReader(reader);
var records = csvReader.GetRecords<Automobile>(); foreach (var r in records)
{
Console.WriteLine(r.ToString());
}
}

最终结果

从结果上看,上面提到的CSV解析痛点,CSVHelper都实现了,特别是针对Comment字段中的逗号、换行、双引号,CSVHelper都处理的很成功。

Tiny CSV Parser

下一个介绍的CSV解析器是Ting CSV Parser, 官网http://bytefish.github.io/TinyCsvParser/index.html, 它是使用配置的方式映射CSV字段, 使用方式上有点类似于AutoMapper

安装

我们可以使用Package Manager Console来安装Tiny CSV Parser。

命令如下:

PM> Install-Package TinyCsvParser

解析CSV

使用Tiny CSV Parser解析CSV文件,首先我们需要创建一个映射类。映射类需要继承自CsvMapping

映射类代码

    public class CsvAutomobileMapping : CsvMapping<Automobile>
{
public CsvAutomobileMapping() : base()
{
MapProperty(0, x => x.Make);
MapProperty(1, x => x.Model);
MapProperty(2, x => x.Type, new EnumConverter<AutomobileType>());
MapProperty(3, x => x.Year);
MapProperty(4, x => x.Price);
MapProperty(5, x => x.Comment, new AutomobileCommentTypeConverter());
}
} public class AutomobileCommentTypeConverter : ITypeConverter<AutomobileComment>
{
public Type TargetType => typeof(AutomobileComment); public bool TryConvert(string value, out AutomobileComment result)
{
result = new AutomobileComment
{
Comment = value
};
return true;
}
}

其中有几个要点,

  • MapProperty是根据列的索引来映射属性的。
  • 当映射枚举时,需要使用EnumConverter来映射。
  • 当映射子对象的时候,需要创建子对象对应的Converter, 例如AutomobileCommentTypeConverter

然后我们修改Program.cs, 使用CsvParser来解析sample.txt

    CsvParserOptions csvParserOptions = new CsvParserOptions(true, ',');
var csvParser = new CsvParser<Automobile>(csvParserOptions, new CsvAutomobileMapping());
var records = csvParser.ReadFromFile("sample.txt", Encoding.UTF8); foreach (var r in records)
{
if (r.IsValid)
{
Console.WriteLine(r.Result.ToString());
} }

最终结果

从结果上看,Tiny CSV Parser实现了大部分CSV解析的痛点,唯一不支持的是字符串换行,这一点需要注意。

效率比较

文章的最后,作者使用Benchmark对CSVHelper和Tiny CSV Parser进行了效率比较。

测试代码如下:

    [MemoryDiagnoser]
public class CsvBenchmarking
{
[Benchmark(Baseline =true)]
public IEnumerable<Automobile> CSVHelper()
{
TextReader reader = new StreamReader("import.txt");
var csvReader = new CsvReader(reader);
var records = csvReader.GetRecords<Automobile>();
return records.ToList();
} [Benchmark]
public IEnumerable<Automobile> TinyCsvParser()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, ',');
var csvParser = new CsvParser<Automobile>(csvParserOptions, new CsvAutomobileMapping()); var records = csvParser.ReadFromFile("import.txt", Encoding.UTF8); return records.Select(x => x.Result).ToList();
}
}

当测试100000行数据的时候

当测试1000000行数据的时候

从测试结果上看

Tiny Csv Parser的效率比CSVHelper高很多,内存占用也少很多。

最终结论

  • 当不需要支持字符串换行的时候,请使用Tiny Csv Parser
  • 当需要支持字符串换行的时候,请使用CSVHelper

附源代码

.NET Core中的CSV解析库的更多相关文章

  1. C 封装一个csv 解析库

    引言 最经关于基础C开发框架基本都搭建好了. 在研究githup,准备传上去. 可惜的是两会连githup 都登陆不进去. 三观很正的我也觉得, 这样不好. 双向标准, 共x党不是一个代表穷苦大众的党 ...

  2. python 中的json解析库

    当一个json 数据很大的时候.load起来是很耗时的.python中常见的json解析库有cjson,simplesjson,json, 初步比较了一下, 对于loads来讲 simplejson ...

  3. .NET Core中的性能测试工具BenchmarkDotnet

    背景介绍 之前一篇博客中,我们讲解.NET Core中的CSV解析库,在文章的最后,作者使用了性能基准测试工具BenchmarkDotNet测试了2个不同CSV解析库的性能,本篇我们来详细介绍一下Be ...

  4. ASP.NET Core中的数据保护

    在这篇文章中,我将介绍ASP.NET Core 数据保护系统:它是什么,为什么我们需要它,以及它如何工作. 为什么我们需要数据保护系统? 数据保护系统是ASP.NET Core使用的一组加密api.加 ...

  5. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  6. Papa Parse – 超强大的多线程 CSV 文本解析库

    Papa Parse 是一个与众不同的,在网页上运行的第一个多线程的 CSV 解析器.它可以解析千兆字节大小文件而不会导致浏览器崩溃.它能够正确地处理格式不正确或边缘的情况下的 CSV 文本.它可以分 ...

  7. CSV.js – 用于 CSV 解析和编码的 JS 工具库

    逗号分隔值(CSV )文件用于以以纯文本的形式存储表格化数据(数字和文本). CSV 文件包含任意数量的记录,通过某种换行符分隔,每条记录由字段,其他一些字符或字符串分隔,最常用的是文字逗号或制表符. ...

  8. 在.NET Core中使用Irony实现自己的查询语言语法解析器

    在之前<在ASP.NET Core中使用Apworks快速开发数据服务>一文的评论部分,.NET大神张善友为我提了个建议,可以使用Compile As a Service的Roslyn为语 ...

  9. C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入

    C# 嵌入dll   在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形 ...

随机推荐

  1. 2018-2019 20165319 网络对抗 Exp4 恶意代码分析

    基础问题回答 1. 如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监控下系统一天天的到底在干些什么.请设计下你想监控的操作有哪些,用什么方法来监控 答:1.使用Windows自带的schta ...

  2. vue v-for循环的用法

    1.v-for循环普通数组 ①创建vue对象 ② 循环数据 结果: 2.v-for循环对象数组 ① 创建vue实例对象 ② 循环对象数组 结果: 3.v-for循环对象 ①创建vue对象实例 ②循环对 ...

  3. PLS:利用PLS(两个主成分的贡献率就可达100%)提高测试集辛烷值含量预测准确度并《测试集辛烷值含量预测结果对比》—Jason niu

    load spectra; temp = randperm(size(NIR, 1)); P_train = NIR(temp(1:50),:); T_train = octane(temp(1:50 ...

  4. ORA-01455

    Oracle 用exp 导出数据库的时候,可能会遇到这个错误: Encountering errors in Export logfileEXP-00008: Oracle error # encou ...

  5. python文件的路径问题补充上一篇内容

    上次的路径问题还没解决就被勒索病毒的木马器给搞了两周多, 拖拖拖到现在又开始纠结路径问题...还是学习能力不足啊... 补充一下路径问题的知识, 毕竟jupyter notebook跟IDE测试的时候 ...

  6. buils tool是什么?为什么使用build tool?java主流的build tool

    定义: build tool是可以自动由源代码创建可执行的应用程序的程序. Building 包括编译.链接和打包代码成一个可用的或可执行形式. 在小型项目,开发人员常常会手动调用构建过程.在更大的项 ...

  7. [OC] NSTimer

    注意NSTimer的销毁 NSTimer在初始化之后,加入RunLoop会导致当前界面被强引用, 所以不会执行dealloc, 需要在合适在逻辑上进行NSTimer的销毁 [_timer invali ...

  8. 第n次搭建 SSM 框架

    什么说第 N 次搭建SSM框架呢? 刚学习java的时候,搭建 SSM 框架想做一个个人项目之类的,后来没搭起来,也就拖延了,进入公司之后,接触的第一个项目就是SSM的,模仿了一下,也能搭个简简单单的 ...

  9. webpack学习--安装

    webpack需要在node环境运行,可以去node官网进行下载安装包:http://nodejs.cn/download/ 1.打开cmd命令窗口,运行node -v 2.全局安装webpack:n ...

  10. 了解vue APi

    阳光那么好,何必自寻烦恼,过好每一个当下,一万个美丽的未来抵不过一个温暖的现在. 一.Vue.nextTick(): 该api 是在Dom节点更新结束之后执行的一个延时回调.在修改数据之后,立即使用这 ...