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

贊助商

分類(lèi)目錄

贊助商

最新文章

搜索

11示例教你用C# .NET CsvHelper讀寫(xiě)CSV文件(1)

作者:admin    時(shí)間:2023-5-19 15:52:38    瀏覽:

C# .NET 使用 CsvHelper 讀寫(xiě)CSV文件,是一個(gè)簡(jiǎn)單易用的值得推薦的方法,在前文中,我詳細(xì)介紹了 CsvHelper 的特征、用法等知識(shí),在本文中,將通過(guò)11個(gè)示例詳細(xì)介紹如何使用 CsvHelper 讀寫(xiě)CSV文件。

先決條件

以下是使用 CsvHelper 所需的一些先決條件,這些是使用 CsvHelper 時(shí)隱含的 .NET 基礎(chǔ)知識(shí)。

使用和處置

每當(dāng)你有一個(gè)對(duì)象實(shí)現(xiàn)IDisposable時(shí),你需要在用完資源時(shí)釋放它。大多數(shù)使用非托管資源的類(lèi)都將實(shí)現(xiàn)IDisposable,這意味著System.IO命名空間中的許多類(lèi)都需要被銷(xiāo)毀。

處理完對(duì)象的最佳做法是將代碼包裝在一個(gè)using塊中,當(dāng)using塊退出時(shí),資源將盡快自動(dòng)處理。

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

如果你需要保留它一段時(shí)間并在以后處理它,using為你做一些錯(cuò)誤處理,所以使用它而不是Dispose直接調(diào)用仍然是個(gè)好主意。

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

讀寫(xiě)文件

要打開(kāi)文件進(jìn)行讀取或?qū)懭?,我們可以使?code>System.IO.File。

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

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

這些都返回一個(gè)FileStream用于處理我們的文件。由于我們的數(shù)據(jù)是文本,因此我們需要使用 StreamReaderStreamWriter 來(lái)讀寫(xiě)文本。

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有執(zhí)行此操作的快捷方式。

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

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

CsvHelper 對(duì)你的編碼一無(wú)所知,因此如果你有特定的編碼,則需要在流中指定它。

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

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

CsvReaderCsvWriter 在他們的構(gòu)造函數(shù)中使用 TextReaderTextWriter。TextReaderTextWriter是閱讀和寫(xiě)作文本的abstract類(lèi)。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

從流中讀取時(shí),如果需要回到流的開(kāi)頭,可以使用 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();
}

寫(xiě)入文件時(shí),需要刷新寫(xiě)入器才能將數(shù)據(jù)寫(xiě)入流。StreamWriter 包含一個(gè)內(nèi)部緩沖區(qū),數(shù)據(jù)僅在緩沖區(qū)已滿或被調(diào)用Flush時(shí)寫(xiě)入流。當(dāng)using塊退出時(shí)自動(dòng)調(diào)用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文件[示例]

獲得類(lèi)記錄

將 CSV 行轉(zhuǎn)換為類(lèi)對(duì)象。

數(shù)據(jù)

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; }
}

獲取動(dòng)態(tài)記錄

將 CSV 行轉(zhuǎn)換為動(dòng)態(tài)對(duì)象。由于無(wú)法確定屬性應(yīng)該是什么類(lèi)型,因此動(dòng)態(tài)對(duì)象上的所有屬性都是字符串。

數(shù)據(jù)

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>();
    }
}

獲取匿名類(lèi)型記錄

將 CSV 行轉(zhuǎn)換為匿名類(lèi)型對(duì)象。你只需要提供匿名類(lèi)型定義。

數(shù)據(jù)

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);
    }
}

枚舉類(lèi)記錄

將 CSV 行轉(zhuǎn)換為在可枚舉的每次迭代中重復(fù)使用的類(lèi)對(duì)象。每個(gè)枚舉都會(huì)混合給定的記錄,但僅限于映射的成員。如果你提供了一個(gè)映射但沒(méi)有映射其中一個(gè)成員,則該成員將不會(huì)與當(dāng)前行的數(shù)據(jù)混合。當(dāng)心在強(qiáng)制IEnumerable評(píng)估的投影上調(diào)用的任何方法,例如ToList(),你將獲得一個(gè)列表,其中所有記錄都是你提供的與 CSV 文件中的最后一條記錄混合的相同實(shí)例。

數(shù)據(jù)

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; }
}

手動(dòng)讀取

有時(shí)出于各種原因,不嘗試配置映射以匹配你的類(lèi)定義會(huì)更容易。通常只需要多幾行代碼就可以手動(dòng)讀取行。

數(shù)據(jù)

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; }
}

讀取多個(gè)數(shù)據(jù)集

出于某種原因,存在包含多組 CSV 數(shù)據(jù)的 CSV 文件。你應(yīng)該能夠毫無(wú)問(wèn)題地讀取這樣的文件。你將需要檢測(cè)何時(shí)更改要檢索的類(lèi)類(lèi)型。

數(shù)據(jù)

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);
    }
}

讀取多種記錄類(lèi)型

如果你有 CSV 數(shù)據(jù),其中每一行可能是不同的記錄類(lèi)型,你應(yīng)該能夠根據(jù)行類(lèi)型或類(lèi)似的東西讀取。

數(shù)據(jù)

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);
    }
}

寫(xiě)CSV文件[示例]

由于篇幅有限,CsvHelper 寫(xiě)CSV文件[示例]請(qǐng)參閱下一篇文章:

相關(guān)文章

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