技術(shù)頻道導(dǎo)航
HTML/CSS
.NET技術(shù)
IIS技術(shù)
PHP技術(shù)
Js/JQuery
Photoshop
Fireworks
服務(wù)器技術(shù)
操作系統(tǒng)
網(wǎng)站運(yùn)營

贊助商

分類目錄

贊助商

最新文章

搜索

TinyCsvParser - 使用C#解析CSV數(shù)據(jù)

作者:admin    時(shí)間:2023-5-19 23:50:41    瀏覽:

關(guān)于使用C#解析、讀寫CSV數(shù)據(jù),前面我已經(jīng)介紹過幾個(gè)方法,可參閱下面文章。

本文中,我將介紹另一個(gè)方法,那就是使用 TinyCsvParser , 一個(gè)CSV解析器。

TinyCsvParser 介紹

TinyCsvParser 是一個(gè) .NET 庫,用于以簡單的方式解析 CSV 數(shù)據(jù),同時(shí)提供非常高性能和非常干凈的 API。它是高度可配置的,以提供最大的靈活性。

TinyCsvParser 支持 .NET Core。

我們可以在 github 查看 TinyCsvParser 的最新信息、使用說明及發(fā)行版本,并下載它:

https://github.com/bytefish/TinyCsvParser

我們還可以使用 NuGet 包。要安裝 TinyCsvParser ,請(qǐng)?jiān)诔绦虬芾砥骺刂婆_(tái)中運(yùn)行以下命令。

PM> Install-Package TinyCsvParser

基本用法

想象一下,我們?cè)?CSV 文件中有一個(gè)人的列表,其中包含他們的名字、姓氏和生日。

Philipp;Wagner;1986/05/12
Max;Musterman;2014/01/02

我們系統(tǒng)中相應(yīng)的域模型可能如下所示。

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
}

使用TinyCsvParser時(shí),必須定義 CSV 數(shù)據(jù)中的列與域模型中的屬性之間的映射。

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設(shè)置為跳過標(biāo)題,使用\n為行分隔符和;為列分隔符。

高級(jí)用法

自定義類型轉(zhuǎn)換器

現(xiàn)在想象一下,你的客戶突然將一個(gè)人的生日更改為一種奇怪的格式,并像這樣寫日期2004###01###25。我們無法使用默認(rèn)轉(zhuǎn)換器解析此類日期格式,但在TinyCsvParser中,我們可以輕松定義DateTimeConverter具有自定義日期時(shí)間格式。

映射屬性時(shí),你可以使用WithCustomConverter方法覆蓋默認(rèn)轉(zhuǎn)換器。我們用給定的格式yyyy###MM###dd實(shí)例化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"));
    }
}

然后讓我們編寫一個(gè)單元測(cè)試來驗(yàn)證預(yù)期的結(jié)果。

[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 發(fā)揮作用

解析器返回一個(gè)ParallelQuery,可用于對(duì)數(shù)據(jù)執(zhí)行其他處理。我認(rèn)為 LINQ 是 C# 中最神奇的東西之一!我能夠在根本不處理鎖或線程的情況下并行化整個(gè)解析。

在這個(gè)例子中,我們將解析數(shù)據(jù)并搜索所有 first name 含有Philipp的名字 。看看我們?nèi)绾胃静恍枰帉?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);
}

總結(jié)

本文介紹了一個(gè)解析CSV數(shù)據(jù)的方法——TinyCsvParser,它在 C# 中構(gòu)建了一個(gè)干凈、易于使用且高性能的 CSV 解析庫。

有關(guān)解析CSV的方法,我曾介紹過其他一些,你可參閱以下文章:

 

標(biāo)簽: TinyCsvParser  CSharp  asp.net  CSV  
x
  • 站長推薦
/* 左側(cè)顯示文章內(nèi)容目錄 */