Kapela.Tools.Csv 10.2.0

Prefix Reserved
dotnet add package Kapela.Tools.Csv --version 10.2.0
                    
NuGet\Install-Package Kapela.Tools.Csv -Version 10.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Kapela.Tools.Csv" Version="10.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Kapela.Tools.Csv" Version="10.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Kapela.Tools.Csv" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Kapela.Tools.Csv --version 10.2.0
                    
#r "nuget: Kapela.Tools.Csv, 10.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Kapela.Tools.Csv@10.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Kapela.Tools.Csv&version=10.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Kapela.Tools.Csv&version=10.2.0
                    
Install as a Cake Tool

📦 Kapela.Tools.Csv

Bibliothèque .NET pour la sérialisation, la désérialisation, l'import et l'export de fichiers CSV.

🚀 Installation

dotnet add package Kapela.Tools.Csv

⚠️ Breaking changes

Cette version est non rétrocompatible avec les versions inférieures à 10.1.0.

Élément modifié Avant Après
CsvSerializer n'hérite plus de CsvSerializerOptions — les options sont regroupées dans Options csv.Separator = ';'; services.AddKapelaCsvSerializer(o => { o.Separator = ';'; });
FieldsMapping et CustomHeader déplacés vers les options csv.Serialize(list, fieldsMapping: "Col1;Col2") services.AddKapelaCsvSerializer(o => { o.FieldsMapping = "Col1;Col2"; });
Validate() n'accepte plus de paramètre rules csv.Validate(content, rules) services.AddKapelaCsvSerializer(o => { o.ValidationRules = [...]; });
SetFormatter<T>() supprimé — utiliser Options.Formatters avec CsvFormatterType csv.SetFormatter<decimal>(new CsvFieldFormatter { ... }) options.Formatters = [new CsvFieldFormatter { Type = CsvFormatterType.Decimal, ... }]
Options.Formatters et Options.ValidationRules sont maintenant IReadOnlyList<T> options.Formatters.Add(...) Assigner la liste complète à l'enregistrement
CsvFieldFormatter et CsvValidationRule convertis en record — propriétés init var f = new CsvFieldFormatter(); f.Format = "N2"; var f = new CsvFieldFormatter { Format = "N2" };

💉 Injection de dépendances

L'approche recommandée est d'enregistrer CsvSerializer dans le conteneur d'injection de dépendances, puis de le recevoir par le constructeur.

// Instance par défaut (Transient)
services.AddKapelaCsvSerializer();

// Avec configuration
services.AddKapelaCsvSerializer(options =>
{
    options.Separator = ',';
    options.Culture = new CultureInfo("en-US");
});

// Depuis IConfiguration (section "CsvSerializer" par défaut)
services.AddKapelaCsvSerializer(configuration);
// Réception par le constructeur
public class MonService(CsvSerializer csv)
{
    public void Exporter(IEnumerable<MonObjet> liste)
    {
        var content = csv.Serialize(liste);
        csv.ExportToFile(content, "export.csv");
    }
}

🏷️ Instances nommées

// Enregistrement
services.AddKapelaCsvSerializer("Import", options => { options.Separator = ';'; });
services.AddKapelaCsvSerializer("Export", options => { options.Separator = ','; });

// Réception via la factory
public class MonService(CsvSerializerFactory factory)
{
    private readonly CsvSerializer _import = factory.CreateCsvSerializer("Import");
    private readonly CsvSerializer _export = factory.CreateCsvSerializer("Export");
}

📄 Configuration depuis appsettings.json

La section "CsvSerializer" est interprétée automatiquement selon sa structure.

Instance par défaut — la section contient directement les propriétés de configuration :

{
  "CsvSerializer": {
    "Separator": ";",
    "Culture": "fr-FR",
    "HasHeader": true,
    "RemoveEmptyLines": true,
    "Mode": "Strict",
    "FieldsMapping": "Nom;Prenom;Age",
    "CustomHeader": "Nom de famille;Prénom;Âge",
    "ValidationRules": [
      { "Index": 0, "RegEx": "^\\d+$", "RegexLabel": "Numérique" }
    ],
    "Formatters": [
      { "Type": "datetime", "Format": "yyyy-MM-dd" },
      { "Type": "decimal", "FieldName": "Montant", "Format": "N2" }
    ],
    "ErrorMessages": {
      "FieldCountMismatch": "Column count {0} differs from header {1}",
      "TypeMismatch": "Cannot convert '{0}' to '{1}' for '{2}'",
      "RegexFailed": "Field '{0}' does not match rule '{1}'",
      "UnsupportedType": "Unsupported property type '{0}'"
    },
    "NewLineReplacement": ". "
  }
}

Les valeurs de "Type" correspondent aux constantes de CsvFormatterType et sont insensibles à la casse.

Instances nommées — la section contient des sous-sections dont chaque clé devient un nom d'instance :

{
  "CsvSerializer": {
    "Export": { "Separator": ",", "Culture": "en-US" },
    "Import": { "Separator": "|" }
  }
}
// Un seul appel enregistre toutes les instances nommées
services.AddKapelaCsvSerializer(configuration);

**Attention 😗* ne pas nommer une instance avec un nom réservé (Separator, Culture, HasHeader, RemoveEmptyLines, Mode, ValidationRules, Formatters, FieldsMapping, CustomHeader, ErrorMessages, NewLineReplacement). Ces noms sont utilisés pour détecter automatiquement si la section contient une instance par défaut ou des instances nommées.


⚙️ Configuration

Toutes les options sont accessibles via la propriété Options du CsvSerializer injecté.

Propriété Type Défaut Description
Separator char ; Séparateur de champs
Culture CultureInfo fr-FR Culture utilisée pour les conversions numériques et dates
HasHeader bool true Indique si le CSV contient une ligne d'entête
RemoveEmptyLines bool true Supprime les lignes vides à l'import
Mode CsvSerializerMode Strict Mode de désérialisation (Strict ou Mapping)
FieldsMapping string? null Sélection et ordre des colonnes (ex : "Nom;Prenom;Age")
CustomHeader string? null Entête personnalisée à la place de l'entête générée automatiquement
ValidationRules IReadOnlyList<CsvValidationRule> [] Règles de validation appliquées par Validate()
Formatters IReadOnlyList<CsvFieldFormatter> [] Formatters de champs
ErrorMessages CsvErrorMessages (messages FR) Messages d'erreur (personnalisables pour l'internationalisation)
NewLineReplacement string ". " Chaîne de remplacement des retours à la ligne dans les champs quotés à l'import

📦 CsvContent — le type central

CsvContent est l'objet pivot du package. Toutes les opérations produisent ou consomment un CsvContent :

Serialize ──► CsvContent ──► ExportToFile / ToBinary / ToString
ImportFromFile / ImportFromBinary / ImportFromString ──► CsvContent ──► Deserialize / Validate

Il représente un contenu CSV en mémoire sous forme d'une liste de lignes (string).

Propriétés

Propriété Type Description
FullContent IList<string> Toutes les lignes (entête incluse si présente)
Header string Première ligne si le CSV a une entête, sinon chaîne vide
Content IEnumerable<string> Lignes de données (sans l'entête)

Méthodes

CsvContent content = csv.Serialize(maListe);

// En chaîne de caractères
string texte = content.ToString();

// En tableau d'octets (incluant le BOM si l'encoding en possède un)
byte[] octets = content.ToBinary();
byte[] octetsUtf8 = content.ToBinary(Encoding.UTF8);

// Accès aux lignes
string entete = content.Header;
IEnumerable<string> lignes = content.Content;

📤 Sérialisation

Dans les exemples suivants, csv est une instance de CsvSerializer reçue par injection de dépendances.

CsvContent content = csv.Serialize(maListe);

Sélectionner et ordonner les colonnes

csv.Options.FieldsMapping = "Nom;Prenom;Age";
CsvContent content = csv.Serialize(maListe);

Entête personnalisée

csv.Options.CustomHeader = "Nom de famille;Prénom;Âge";
CsvContent content = csv.Serialize(maListe);

📥 Désérialisation

CsvDeserializationResult<MonObjet> result = csv.Deserialize<MonObjet>(content);

foreach (var item in result.Datas)
    Console.WriteLine(item.Nom);

foreach (var error in result.Errors)
    Console.WriteLine(error);

Types supportés

Type Nullable Notes
string Valeur brute
int int? NumberStyles.Any, culture-aware
decimal decimal? NumberStyles.Any, culture-aware
DateTime DateTime? Format exact (via formatter), OLE Automation, ou culture-aware
bool bool? BoolTrueValue/BoolFalseValue via formatter, ou Boolean.TryParse
Guid Guid? Format "D" par défaut, configurable ("N", "B", "P", "X")
Enums Enum? Par nom (insensible à la casse) ou par valeur numérique

🔀 Modes de désérialisation

Mode Comportement
Strict (défaut) Mappe colonne par colonne dans l'ordre. Génère une erreur si le nombre de champs ne correspond pas.
Mapping Mappe par nom d'entête. Tolère les colonnes manquantes ou supplémentaires.
// Via options (configuré à l'enregistrement)
services.AddKapelaCsvSerializer(options => { options.Mode = CsvSerializerMode.Mapping; });

// Via attribut sur la classe de destination (prioritaire sur les options)
[CsvSerializerMode(CsvSerializerMode.Mapping)]
public class MonObjet { ... }

📁 Import / Export

// Import depuis un fichier, un tableau d'octets ou une chaîne
var content = csv.ImportFromFile("donnees.csv");
var content2 = csv.ImportFromBinary(tableauOctets);
var content3 = csv.ImportFromString("Id;Nom\n1;Alice");

// Export (avec encoding optionnel)
csv.ExportToFile(content, "export.csv");
csv.ExportToFile(content, "export.csv", Encoding.UTF8);

🏷️ Attributs

[CsvSerializer] — sur une propriété

Personnalise l'entête ou exclut une propriété.

public class Client
{
    [CsvSerializer(Header = "Identifiant")]
    public int Id { get; set; }

    public string Nom { get; set; }

    [CsvSerializer(Ignore = true)]
    public string MotDePasse { get; set; }
}

[CsvSerializerFormat] — sur une propriété

Définit le format d'un champ. Prioritaire sur les formatters globaux.

public class Commande
{
    [CsvSerializerFormat(Format = "yyyy-MM-dd")]
    public DateTime DateCommande { get; set; }

    [CsvSerializerFormat(Format = "N2")]
    public decimal Montant { get; set; }

    [CsvSerializerFormat(BoolTrueValue = "OUI", BoolFalseValue = "NON")]
    public bool EstValide { get; set; }
}

[CsvSerializerMode] — sur une classe

Surcharge le mode de désérialisation pour ce type spécifique.

[CsvSerializerMode(CsvSerializerMode.Mapping)]
public class MonObjet { ... }

🎨 Formatters

Les formatters s'appliquent globalement à un type ou à un champ spécifique. Ils sont définis via Options.Formatters à l'enregistrement par injection de dépendances, ou directement sur l'instance.

La propriété Type de CsvFieldFormatter doit être renseignée avec une constante de la classe CsvFormatterType :

services.AddKapelaCsvSerializer(options =>
{
    options.Formatters =
    [
        // Toutes les dates au format yyyy-MM-dd
        new CsvFieldFormatter { Type = CsvFormatterType.DateTime, Format = "yyyy-MM-dd" },

        // Uniquement le champ "Montant" avec 2 décimales
        new CsvFieldFormatter { Type = CsvFormatterType.Decimal, FieldName = "Montant", Format = "N2" },

        // Valeurs booléennes personnalisées
        new CsvFieldFormatter { Type = CsvFormatterType.Bool, BoolTrueValue = "OUI", BoolFalseValue = "NON" },

        // Deux formatters pour le même type, ciblant des champs différents
        new CsvFieldFormatter { Type = CsvFormatterType.Int, FieldName = "Id", Format = "D6" },
        new CsvFieldFormatter { Type = CsvFormatterType.Int, FieldName = "Code", Format = "D4" }
    ];
});

Types disponibles

Constante Valeur Type ciblé
CsvFormatterType.Int "int" int
CsvFormatterType.Decimal "decimal" decimal
CsvFormatterType.DateTime "datetime" DateTime
CsvFormatterType.Bool "bool" bool
CsvFormatterType.String "string" string
CsvFormatterType.Guid "guid" Guid

Les enums sont également supportés sans nécessiter de constante CsvFormatterType. Ils sont sérialisés par nom par défaut. Pour obtenir la valeur numérique, appliquer [CsvSerializerFormat(Format = "D")] sur la propriété. La désérialisation accepte le nom (insensible à la casse) ou la valeur numérique.

**Priorité 😗* [CsvSerializerFormat] sur la propriété > formatter par FieldName > formatter global (sans FieldName).


✅ Validation

// Configuré à l'enregistrement
services.AddKapelaCsvSerializer(options =>
{
    options.ValidationRules =
    [
        new CsvValidationRule { Index = 0, RegEx = @"^\d+$", RegexLabel = "La colonne 0 doit être numérique" },
        new CsvValidationRule { Index = 1, RegEx = @"^.{1,50}$", RegexLabel = "La colonne 1 doit faire entre 1 et 50 caractères" }
    ];
});

// Validation
CsvValidationResult result = csv.Validate(content);

if (!result.Success)
{
    foreach (var detail in result.Errors)
        Console.WriteLine($"Ligne {detail.Line} : {string.Join(", ", detail.Errors.Select(e => e.Error))}");
}

➕ Ajouter des erreurs de validation personnalisées

CsvValidationResult expose une méthode AddError permettant d'enrichir le résultat avec des règles métier que le package ne peut pas gérer nativement. Si une erreur est ajoutée sur une ligne déjà présente dans le résultat, elle est regroupée avec les erreurs existantes de cette ligne.

CsvValidationResult result = csv.Validate(content);

// Enrichissement avec des règles métier
var deserialized = csv.Deserialize<Commande>(content);
foreach (var (commande, index) in deserialized.Datas.Select((x, i) => (x, i + 1)))
{
    if (commande.Montant < 0)
        result.AddError(line: index, message: "Le montant ne peut pas être négatif", index: 3);
}

if (!result.Success)
{
    foreach (var detail in result.Errors)
        Console.WriteLine($"Ligne {detail.Line} : {string.Join(", ", detail.Errors.Select(e => e.Error))}");
}
Paramètre Type Description
line int Numéro de la ligne concernée (commence à 1)
message string Message décrivant l'erreur
index int? Index du champ concerné (optionnel)

🌐 Internationalisation des messages d'erreur

Les messages produits par Validate() et Deserialize() sont configurables via Options.ErrorMessages. Chaque propriété est une chaîne de format (string.Format) dont les paramètres sont décrits en détail dans l'intellisense.

services.AddKapelaCsvSerializer(options =>
{
    options.ErrorMessages = new CsvErrorMessages
    {
        FieldCountMismatch = "Row field count ({0}) doesn't match header ({1})",
        TypeMismatch       = "Cannot parse '{0}' as '{1}' for property '{2}'",
        RegexFailed        = "Field '{0}' failed validation rule '{1}'",
        UnsupportedType    = "Unsupported property type '{0}'"
    };
});
Propriété Paramètres
FieldCountMismatch {0} nombre de champs de la ligne, {1} nombre attendu
TypeMismatch {0} valeur lue, {1} type attendu, {2} nom de la propriété
RegexFailed {0} nom ou index du champ, {1} libellé de la règle
UnsupportedType {0} nom du type

📜 RFC 4180 — Champs quotés

Le parsing et l'écriture CSV respectent la RFC 4180 :

  • Lecture : les champs entourés de guillemets (") sont correctement parsés, y compris s'ils contiennent le séparateur, des guillemets échappés ("") ou des retours à la ligne.
  • Écriture : les valeurs contenant le séparateur, un guillemet ou un retour à la ligne sont automatiquement entourées de guillemets, avec doublement des guillemets internes.

Champs multilignes

Les retours à la ligne trouvés dans un champ quoté sont remplacés par la valeur de Options.NewLineReplacement (par défaut ". ") afin de conserver la structure CsvContent (une entrée = un record).

services.AddKapelaCsvSerializer(options =>
{
    options.NewLineReplacement = " - ";  // Remplace \n par " - " dans les champs quotés
});

Exemple

// Lecture d'un CSV avec champs quotés
var content = csv.ImportFromString("Nom;Adresse\n\"Dupont\";\"12 rue de la Paix\nParis\"");
var result = csv.Deserialize<Client>(content);
// result.Datas.First().Adresse == "12 rue de la Paix. Paris"

// Écriture — le quoting est automatique
var list = new[] { new Client { Nom = "Du;pont", Adresse = "Paris" } };
var output = csv.Serialize(list);
// output.Content.First() contient : "Du;pont";Paris
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Kapela.Tools.Csv:

Package Downloads
Kapela.Tools.Csv.OpenXmlExtensions

Ce package .NET permet d'exporter au format XLSX un contenu CSV

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.2.0 168 4/14/2026
10.1.0 118 4/3/2026
10.0.0 705 12/2/2025
8.3.1 717 12/2/2025
8.2.0 3,659 6/26/2025
8.1.0 203 5/27/2025
8.0.2 194 5/7/2025
8.0.1 990 4/28/2025
1.0.1 647 3/12/2025