Przetwarzanie plików CSV w C# stało się przyjemniejsze – CsvHelper

Dziś chciałabym się podzielić znaleziskiem, którego dokonałam ostatnio – mianowicie bardzo fajną biblioteką do przetwarzania plików CSV. Generalnie nie jest to przyjemna robota, ale z tym narzędziem zrobiło się naprawdę fajnie. Nazywa się CsvHelper a więcej informacji na jej temat można znaleźć tutaj.

By skorzystać z biblioteki musimy ją ściągnąć z NuGeta albo korzystając z wersji okienkowej czyli opcji „Manage NuGet Packages…” albo za pomocą „Package Manager Console” (dostępna z menu Tools->NuGet Package Manager)

Żeby nie przepisywać oryginalnej dokumentacji, która jest dostępna na stronie biblioteki chciałabym raczej pokazać jak to działa w praktyce dlatego też od razu zapraszam do moich przykładów dostępnych na Githubie.

Czytanie plików CSV

Przypadek 1 (Najprostszy): Mamy obiekt, którego pola mają takie same nazwy jak kolumny w pliku csv.

Przykładowy plik:

Name,Surname,Age
Jack,Sparrow,25
Hektor,Barbossa,30

Przykładowy obiekt:

Aby zczytać taki plik i zamapować dane na kolekcję takich obiektów wystarczy, że zrobimy coś takiego:

Jak to działa?

W pierwszej linijce otwieramy plik z danymi i go wczytujemy a w drugiej obiekty są automatycznie mapowane na obiekt User i na koniec dostajemy kolekcję tychże obiektów.

Jednak w życiu nie zawsze bywa tak prosto, więc jeśli takie automagiczne mapowanie u nas z jakiegoś powodu nie znajdzie zastosowania (choćby jeśli nazwy kolumn zawierają spację), możemy zdefiniować je sami.

Przypadek 2: Załóżmy, że model nadal mamy taki jak wyżej ale kolumny w pliku CSV mają nieco inne nazwy.

Przykładowy plik:

UserName,UserSurname,UserAge
Jack,Sparrow,25
Hektor,Barbossa,30

Biblioteka pozwala nam na mapowanie pól obiektu z kolumnami po indeksie kolumny. Czyli możemy zrobić coś takiego:

W drugiej linijce rejestrujemy mapę. Natomiast samo mapowanie będzie wyglądało tak:

Biblioteka pozwala nam na mapowanie pól obiektu z kolumnami również po nazwie kolumny. Czyli możemy zrobić również taką konfigurację:

Jeśli chodzi o mapowanie dostępne są jeszcze bardziej rozbudowane opcje takie jak możliwość konwersji typów, mapowanie w trakcie działania aplikacji lub ustawienie domyślnych wartości dla niektórych pól.

Tworzenie plików CSV

Jednak biblioteka nie ogranicza swoich możliwości tylko do odczytywania plików CSV. Umożliwia nam również ich tworzenie.

Przypadek 1 (Najprostszy): Tworzymy plik CSV w którym nazwy kolumn są takie same jak nazwy pól naszej klasy.

W efekcie otrzymamy plik CSV takiej postaci:

Name,Surname,Age
Jack,Sparrow,23
Davy,Jones,25
Hektor,Barbossa,23

Przypadek 2: Wykorzystujemy mapowanie aby dostosować nazwy kolumn do naszych potrzeb.

Ma to miejsce podobnie jak w przypadku odczytywania plików czyli konfigurujemy mapowanie jak poniżej:

I definiujemy je dokładnie tak samo jak przy odczytywaniu plików.

Konfiguracja

Do tej pory powiedzieliśmy sobie tylko o konfiguracji na potrzeby mapowania, ale opcji dostępnych jest dużo więcej. Możemy ustawić m.in.

  • delimiter czyli znak którym mają być oddzielane wartości w wierszu. Tutaj na przykład ustawiamy jako delimiter średnik:
    reader.Configuration.Delimiter = ";"
  • culture info czyli ustawienia formatowania, daty, czasu itp. odpowiednie dla danego regionu/kraju (kultury)
  • Has Header Record – ważne by było ustawione na True, gdy mapujemy po nazwach kolumn, gdyż jeśli tego nagłówka nie będzie całość nie będzie mogła działać poptawnie.
  • Trim Fields i Trim Headers – pozwala nam automatycznie pozbywać się pustych znaków.

To tyle mojego małego wprowadzenia do biblioteki CSVHelper do której używania zachęcam.

Omawiane przykłady znajdziecie na moim Githubie.

  • jm

    Warto wspomnieć o tym, że CsvHelper wspiera „leniwą inicjalizację”, co się przydaje przy bardzo dużych plikach 🙂

  • Grzegorz Pawluch

    Cześć!

    Dzięki za ten wpis, faktycznie przydatna ta biblioteka.

    Ponieważ klasa CsvWriter implementuje IDisposable, wg mnie należałoby dodać jeszcze jednego „using”.

    using (var streamWriter = File.CreateText(„Pirates.csv”))
    {
    using (var writer = new CsvWriter(streamWriter))
    {
    writer.Configuration.RegisterClassMap();
    writer.WriteRecords(users).ToList();
    }
    }

  • Iwona

    Dokładnie tak. Pominęłam, bo w sumie skupiłam się na tym jak używać, ale masz rację – nie ma co propagować złych praktyk.