.NET Core中的CSV解析库

感谢

本篇首先特别感谢从此启程兄的《.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

附源代码


作者:Lamond Lu
出处:https://www.cnblogs.com/lwqlun/p/9639456.html
本站使用「署名 4.0 国际」创作共享协议,转载请在文章明显位置注明作者及出处。

原文地址:https://www.cnblogs.com/lwqlun/p/9639456.html

时间: 2024-08-29 09:40:36

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

uniVocity-parsers:一款强大的CSV/TSV/定宽文本文件解析库(Java)

uniVocity-parsers 是一个开源的Java项目. 针对CSV/TSV/定宽文本文件的解析,它以简洁的API开发接口提供了丰富而强大的功能.后面会做进一步介绍. 和其他解析库有所不同,uniVocity-parsers以高性能.可扩展为出发点,设计了一套自有架构.基于这套架构,开发者可以构建出新的文件解析器. 1. 概述 作为一名Java开发者,我目前正在参与开发一个Web项目,该项目帮助通信运营商评估当前的网络,并给出解决方案. 在该项目中,CSV文件扮演着至关重要的角色,它是运营

第四部分 解析库的使用(XPath、Beautiful Soup、PyQuery)

在网页节点中,可以定义id.class或其他属性.节点间有层次关系,网页中要通过XPath或CSS选择器定位一个或多个节点.在页面解析时,可利用XPath或CSS选择器提取某个节点,再调用相应方法获取它的正文内容或者属性,就可提取到想要的信息.在python中常用的解析库有lxml.Beautiful Soup.pyquery等.使用这些库可以很大程度上提高效率. 一 使用XPath解析库 XPath,全称XML Path Language,即XML路径语言,是一门在XML文档中查找信息的语言.

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

逗号分隔值(CSV )文件用于以以纯文本的形式存储表格化数据(数字和文本). CSV 文件包含任意数量的记录,通过某种换行符分隔,每条记录由字段,其他一些字符或字符串分隔,最常用的是文字逗号或制表符.CSV.js 是一个简单,超快的用于 CSV 解析和编码的 JavaScript 工具库,兼容浏览器,AMD 和 NodeJS 环境. 您可能感兴趣的相关文章 Web 开发中很实用的10个效果[附源码下载] 精心挑选的优秀jQuery Ajax分页插件和教程 12款经典的白富美型 jQuery 图片

Linux中用户和组中认证库和解析库的文件格式以及默认参数定义文件

解析库:/etc/passwd,/etc/group    组名和组的对应关系 认证库:/etc/shadow,/etc/gshadow  组密码的相关内容存储位置 与用户账户和组账户相关的文件有: /etc/passwd /etc/group /etc/shadow /etc/gshadow /etc/default/useradd /etc/login.defs(登录的默认属性) /etc/skel(家目录默认存储文件) /etc/passwd(用户的相关信息): 用户账户在/etc/pas

NET Core中的认证管理解析

2016-08-19 07:15 0x00 问题来源 在新建.NET Core的Web项目时选择"使用个人用户账户"就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可以使用AuthorizeAttribute进行各种权限管理,看起来似乎十分方便.不过生成的代码都替我干了些什么我一团雾水.看了下生成的数据表,功能也挺复杂的.实际上我需要的只是基于用户和角色的认证管理,而且用户资料是使用现有的库,但使用.NET Core自带的认证组件必须要依赖EF,表的结构

.Net Core下一次针对dpz2.Json和Newtonsoft.Json解析库的简单测试

关于dpz2.Json dpz2.Json是大胖子软件的自研Json解析库. 应用于更加简单的使用场景 在dpz2.Json诞生之前,我们一直使用的是Newtonsoft.Json解析库,Newtonsoft.Json最方便的地方是采用了类似JavaBean的绑定方式进行操作,但是实际操作时,我们可能更多时候只想要个解析器,好让我们能快速的辨别数据,这个时候,单纯的JavaBean方式又变得比较肘制,读取数据使用C#的动态类型确实可以比较方便的进行操作. 专注于直接操作 另外一个促使我们自研一个

解析Asp.net Core中使用Session的方法

2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Core中引用dll,以往我们引用DLL都是直接引用,在Core里这样是不行的,必须基于NuGet添加,或者基于project.json添加,然后保存VS会启动还原类库. 第二就是使用Session的问题,Core里使用Session需要添加Session类库. 添加Session 在你的项目上基于NuGet添

【春华秋实】深入源码理解.NET Core中Startup的注册及运行

原文:[春华秋实]深入源码理解.NET Core中Startup的注册及运行 写在前面 开发.NET Core应用,直接映入眼帘的就是Startup类和Program类,它们是.NET Core应用程序的起点.通过使用Startup,可以配置化处理所有向应用程序所做的请求的管道,同时也可以减少.NET应用程序对单一服务器的依赖性,使我们在更大程度上专注于面向多服务器为中心的开发模式. 目录: Startup讨论 Starup所承担的角色 Startup编写规范 ConfigureServices

[翻译]在 .NET Core 中的并发编程

原文地址:http://www.dotnetcurry.com/dotnet/1360/concurrent-programming-dotnet-core 今天我们购买的每台电脑都有一个多核心的 CPU,允许它并行执行多个指令.操作系统通过将进程调度到不同的内核来发挥这个结构的优点.然而,还可以通过异步 I/O 操作和并行处理来帮助我们提高单个应用程序的性能.在.NET Core中,任务 (tasks) 是并发编程的主要抽象表述,但还有其他支撑类可以使我们的工作更容易. 并发编程 - 异步 v