Fermer

mars 10, 2023

Manipulation de fichiers CSV dans .NET

Manipulation de fichiers CSV dans .NET


La lecture et l’écriture de données sont des tâches courantes dans la routine d’un développeur .NET, mais lorsque la source de données est un fichier, différent de la base de données traditionnelle, de nombreux doutes surgissent. Découvrez dans cet article de blog comment manipuler des données dans des fichiers CSV dans une application .NET.

En tant que développeurs, nous sommes habitués à créer des applications qui lisent des données à partir d’une base de données, qu’elle soit relationnelle ou non, mais ce que beaucoup de gens ne savent pas, c’est qu’il existe d’autres façons de stocker des données, dont les fichiers CSV.

Les fichiers CSV servent à plusieurs fins et constituent un excellent moyen de stocker des données en raison de leur simplicité et de leur polyvalence.

Dans cet article, nous verrons comment utiliser les fichiers CSV dans notre routine de développement et comment implémenter une application .NET qui lit et crée des fichiers CSV.

Pourquoi les fichiers CSV sont-ils utilisés ?

Les fichiers CSV sont des fichiers texte utilisés pour stocker de grandes quantités de données. Il est courant de trouver des fichiers CSV sur les systèmes des grandes entreprises car ils servent à de nombreuses fins commerciales.

Il est possible d’exporter un grand volume de données et d’effectuer des filtres et des tris complexes à travers ce format de fichier, car vos données peuvent être organisées sous forme de tableur en fonction du logiciel utilisé pour les lire.

Comment les fichiers CSV sont-ils utilisés dans la routine d’un développeur ?

En tant que développeur .NET, vous rencontrerez probablement des situations où une manipulation de données à grande échelle est requise. Pour éviter les coûts et les efforts de mise en œuvre d’une base de données, qu’elle soit relationnelle ou non, l’utilisation de fichiers CSV peut être le meilleur choix.

Imaginez le scénario suivant : vous travaillez sur un projet pour une grande place de marché et quelques milliers de produits doivent être désactivés car ils contiennent des données incorrectes. En tant que développeur, vous n’avez pas accès à la base de données qui stocke ces produits, et la seule façon de les désactiver en masse est via l’API.

Vous entrez donc dans le panneau d’administration du marché, filtrez les milliers de produits avec des données incorrectes et générez un fichier CSV avec ces produits. Ensuite, vous créez une API qui lit le fichier et envoie les produits pour inactivation.

Vous réalisez à quel point il peut être simple de résoudre des problèmes à l’aide de fichiers CSV ?

Manipulation de fichiers CSV dans une application .NET

Ensuite, nous allons créer une API minimale dans .NET et manipuler les fichiers CSV via la bibliothèque CsvHelper. CsvHelper est une excellente bibliothèque open source pour travailler avec des fichiers CSV dans .NET.

Concernant le scénario du projet, nous aurons un fichier CSV avec des centaines d’enregistrements de produits, dont beaucoup ont le même code fournisseur, mais nous voulons obtenir un seul exemple de chaque fournisseur. Ainsi, l’application lira le document CSV avec les enregistrements, filtrera et triera, puis enregistrera un exemple de produit pour chaque client dans un autre fichier CSV.

Le code source du projet complet est accessible ici : code source.

Création de l’application

Commençons par créer l’application, puis dans Visual Studio, suivez les étapes ci-dessous :

  • Créer un nouveau projet
  • Choisissez l’API Web ASP.NET Core
  • Choisissez .NET 7.0
  • Décochez l’option pour utiliser des contrôleurs, nous n’en aurons pas besoin dans cet exemple

Ajout des dépendances

Tout d’abord, téléchargeons la dépendance CSV Helper que nous utiliserons plus tard. Pour cela, vous pouvez le télécharger via le lien NuGet d’assistance CSV ou ajoutez le code ci-dessous dans le fichier .csproj du projet :

<PackageReference Include="CsvHelper" Version="30.0.1" />

Notez que dans cet exemple, la version 7.0 de .NET sera utilisée et la version de l’assistant CSV est 30.0.1. Assurez-vous d’utiliser des versions compatibles des deux.

Création des classes de modèle

La première classe de modèle sera CsvFile, qui contiendra les champs correspondant à l’en-tête du fichier CSV. Notez qu’à travers l’attribut [Name()] nous définissons le nom de chaque colonne du fichier CSV lors de la lecture du fichier.

Créez donc un nouveau dossier appelé « Modèles » et à l’intérieur la classe ci-dessous :

using CsvHelper.Configuration.Attributes;

namespace ProductFilter.Models;
public class CsvFile
{
    [Name("sellerId")]
    public string? SellerId { get; set; }

    [Name("productId")]
    public string? ProductId { get; set; }
}

La deuxième classe sera responsable du mappage entre les colonnes du fichier CSV et les propriétés de la classe CsvFile lors de l’écriture des données, c’est-à-dire le processus inverse de la classe précédente où nous avons ajouté les attributs de lecture du fichier.

Ainsi, dans le dossier « Models », créez la classe ci-dessous :

using CsvHelper.Configuration;

namespace ProductFilter.Models;
public class CsvFileMap : ClassMap<CsvFile>
{
    public CsvFileMap()
    {
        Map(m => m.SellerId).Name("sellerId");
        Map(m => m.ProductId).Name("productId");
    }
}

Exécution de la lecture et de l’écriture du fichier CSV

Ensuite, nous allons créer une classe de service qui contiendra la logique nécessaire pour écrire et lire des fichiers. Créez ensuite un nouveau dossier appelé « Service » et ajoutez-y la classe ci-dessous :

using CsvHelper;
using CsvHelper.Configuration;
using ProductFilter.Models;
using System.Globalization;

namespace ProductFilter.Service;

public class ProductService
{
    public void ExecuteService()
    {
        var filteredProducts = new List<CsvFile>();

        ReadCsvFile(filteredProducts);
        WriteCsvFile(filteredProducts);
    }

    public void ReadCsvFile(List<CsvFile> filteredProducts)
    {
        var config = new CsvConfiguration(CultureInfo.InvariantCulture)
        {
            HasHeaderRecord = true,
        };

        using (var reader = new StreamReader("YOUR FILE DIRECTORY\\products.csv"))
        {
            using (var csv = new CsvReader(reader, config))
            {
                var products = csv.GetRecords<CsvFile>().ToList();

                foreach (var product in products)
                {
                    var repeatSeller = products.FindAll(p => p.SellerId == product.SellerId);
                    var filteredProductsAlreadyContainsSeller = filteredProducts.Where(p => p.SellerId == product.SellerId).ToList();

                    if (repeatSeller.Count > 1 && !filteredProductsAlreadyContainsSeller.Any())
                        filteredProducts.Add(product);
                }
            }
        }
    }

    public void WriteCsvFile(List<CsvFile> filteredProducts)
    {
        using (var writer = new StreamWriter("YOUR FILE DIRECTORY\\producstFiltered.csv"))
        {
            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                csv.Context.RegisterClassMap<CsvFileMap>();

                csv.WriteHeader<CsvFile>();
                csv.NextRecord();
                csv.WriteRecords(filteredProducts);
            }
        }
    }
}

Le code ci-dessus contient deux méthodes principales, ReadCsvFile et WriteCsvFile.

Le premier, ReadCsvFile crée une nouvelle instance de StreamReader classe qui reçoit le répertoire où est stocké le fichier CSV. Ensuite, la valeur de la StreamReader variable de classe est utilisée pour créer une instance de la CsvReader class et sa valeur est affectée à la variable csv. Puis, à travers le GetRecords méthode d’extension, les enregistrements sont obtenus à partir du fichier CSV.

Avec les enregistrements obtenus, nous avons réussi à les manipuler. Ainsi, la liste des produits est parcourue et les enregistrements qui ont la répétition sellerId propriété sont trouvées. S’il n’existe pas déjà dans la liste, il est ajouté. De cette façon, à la fin, nous avons une liste avec un produit de chacun des vendeurs.

La deuxième méthode, WriteCsvFilecrée une nouvelle instance de StreamWriter classe qui reçoit le répertoire et le nom du fichier qui sera créé. Puis une nouvelle instance de
CsvWriter classe est créée et affectée au csv variable, puis à travers les méthodes d’extension WriteHeader, NextRecord et WriteRecords le nouveau fichier CSV est créé, contenant les enregistrements obtenus dans la méthode précédente.

Maintenant que la logique de lecture et d’écriture est prête, créez simplement un point de terminaison pour exécuter le service et ainsi vérifier que tout fonctionne comme prévu.

Ainsi, dans le fichier Program.cs ajoutez le code ci-dessous :

builder.Services.AddScoped<ProductService>();

Et après l’extrait de code app.MapControllers(); ajouter ce qui suit :

app.MapPost("/execute", (ProductService service) =>
{
    try
    {
        service.ExecuteService();
        return Results.Ok("Success");
    }
    catch (Exception ex)
    {
        return Results.BadRequest($"Error: {ex.Message}");
    }
});

Exécution de la demande

Avant de lancer l’application, il est nécessaire d’avoir le fichier CSV qui sera lu. Vous pouvez le télécharger ici-Exemple de fichier CSV— puis placez-le dans le répertoire de votre choix, mais il est important de remplacer la section « VOTRE RÉPERTOIRE DE FICHIERS » par le répertoire où se trouve le fichier CSV.

Maintenant, exécutez simplement le projet et l’interface Swagger s’ouvrira dans le navigateur. Lors de l’exécution de la route « /execute », le fichier products.csv sera lu et les enregistrements traités seront écrits dans le fichier productFiltered.csv, comme indiqué dans le GIF ci-dessous :

Essai d'exécution

Conclusion

Les fichiers CSV sont parfaits pour travailler avec de grandes quantités de données en raison de leur simplicité et de leur faible coût.

Dans cet article, nous avons appris à lire et à écrire des fichiers CSV via la bibliothèque CSVHelper, mais il existe encore plusieurs autres ressources disponibles pour travailler avec ce type de fichier, alors n’hésitez pas à les explorer dans vos prochains projets, et n’oubliez pas d’utiliser eux quand l’occasion se présente.




Source link