194 votes

Lecture du fichier csv

Besoin d'aide ! J'écris une application d'importation simple et j'ai besoin de lire un fichier csv. Afficher le résultat dans une grille de données et afficher les lignes corrompues du fichier csv dans une autre grille, par exemple afficher les lignes qui sont plus courtes que 5 valeurs dans une autre grille. J'essaie de faire cela comme ceci :

StreamReader sr = new StreamReader(FilePath);
importingData = new Account();
string line;
string[] row = new string [5];
while ((line = sr.ReadLine()) != null)
{
    row = line.Split(',');

        importingData.Add(new Transaction
        {
            Date = DateTime.Parse(row[0]),
            Reference = row[1],
            Description = row[2],
            Amount = decimal.Parse(row[3]),
            Category = (Category)Enum.Parse(typeof(Category), row[4])
        });
}

mais il est très difficile d'opérer sur des tableaux dans ce cas. Existe-t-il un meilleur moyen de diviser les valeurs ? Toute suggestion est la bienvenue.

Merci. Les informations que vous avez fournies ont été très utiles. J'ai trouvé un autre moyen de faire cela en utilisant DataTable. Approche très intéressante, voici le lien : texte du lien

0 votes

Merci pour votre solution. Pensez à la poster en tant que réponse - l'inclure dans la question n'aide pas à sa lisibilité.

0 votes

393voto

David Pokluda Points 4284

Ne réinventez pas la roue. Tirez parti de ce qui se trouve déjà dans la BCL .NET.

  • ajoutez une référence à Microsoft.VisualBasic (oui, c'est écrit VisualBasic, mais cela fonctionne aussi bien en C# - n'oubliez pas qu'à la fin, tout cela n'est qu'un IL)
  • utiliser la classe Microsoft.VisualBasic.FileIO.TextFieldParser pour analyser un fichier CSV

Voici l'exemple de code : (Voir également le deuxième exemple ci-dessous)

TextFieldParser parser = new TextFieldParser(@"c:\temp\test.csv");
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData) 
{
    //Processing row
    string[] fields = parser.ReadFields();
    foreach (string field in fields) 
    {
        //TODO: Process field
    }
}
parser.Close();

Il fonctionne très bien pour moi dans mes projets C#. Essayez-le.

Edit : Voici quelques liens/informations supplémentaires


Parce que TextFieldParser met en œuvre IDisposable il est préférable d'utiliser l'option using avec elle :

using (TextFieldParser parser = new TextFieldParser(@"c:\temp\test.csv"))
{
    parser.TextFieldType = FieldType.Delimited;
    parser.SetDelimiters(",");
    while (!parser.EndOfData) 
    {
        //Processing row
        string[] fields = parser.ReadFields();
        foreach (string field in fields) 
        {
            //TODO: Process field
        }
    }
}

20 votes

J'aurais VRAIMENT aimé qu'il y ait un moyen qui n'utilise pas les bibliothèques VB, mais ceci a parfaitement fonctionné ! Merci !

6 votes

+1 : Je viens de casser le lecteur CSV rapide de Lumenworks sur un fichier de 53Mo. Il semble que la mise en cache des lignes ait échoué après 43 000 lignes et ait brouillé le tampon. J'ai essayé le VB TextFieldParser et ça a fait l'affaire. Merci

11 votes

+1 Excellente réponse, car je constate que beaucoup de gens ne savent pas que cette classe existe. Une chose à noter pour les futurs téléspectateurs est que le paramètre parser.TextFieldType = FieldType.Delimited; n'est pas nécessaire si vous appelez parser.SetDelimiters(","); car la méthode fixe le TextFieldType propriété pour vous.

38voto

adrianm Points 7067

D'après mon expérience, il existe de nombreux formats csv différents. En particulier la façon dont ils gèrent l'échappement des guillemets et des délimiteurs dans un champ.

Ce sont les variantes que j'ai rencontrées :

  • les citations sont citées et doublées (excel), c'est-à-dire 15" -> champ1, "15"",champ3
  • les guillemets ne sont pas modifiés, sauf si le champ est cité pour une autre raison. Par exemple, 15" -> champ1,15",champs3
  • Les guillemets sont échappés avec \. c'est-à-dire 15" -> champ1, "15\"",champ3
  • les guillemets ne sont pas du tout modifiés (il n'est pas toujours possible de les analyser correctement).
  • le délimiteur est entre guillemets (excel). c'est-à-dire a,b -> champ1, "a,b",champ3
  • Le délimiteur est échappé avec \. c'est-à-dire a,b -> champ1,a\,b,champ3

J'ai essayé de nombreux analyseurs csv existants, mais aucun d'entre eux n'est capable de gérer les variantes que j'ai rencontrées. Il est également difficile de savoir, à partir de la documentation, quelles variantes d'échappement les analyseurs supportent.

Dans mes projets, j'utilise maintenant soit le TextFieldParser de VB, soit un séparateur personnalisé.

1 votes

J'adore cette réponse pour les cas de test que vous avez fournis !

2 votes

Le principal problème est que la plupart des implémentations ne se soucient pas de la RFC 4180 qui décrit le format CSV et la manière dont les délimiteurs doivent être échappés.

0 votes

La RFC-4180 date de 2005, ce qui semble ancien aujourd'hui, mais n'oubliez pas que le cadre .Net est apparu en 2001. En outre, les RFC ne sont pas toujours des normes officielles et, dans ce cas, elles n'ont pas le même poids que, par exemple, l'ISO-8601 ou la RFC-761.

7voto

Keith Blows Points 823

Les CSV peuvent être compliqués réel rapide.

Utilisez quelque chose de robuste et de bien testé :
FileHelpers : www.filehelpers.net

Les FileHelpers sont une bibliothèque .NET gratuite et facile à utiliser pour importer/exporter des données à partir d'enregistrements de longueur fixe ou délimités dans des fichiers, des chaînes ou des flux.

5 votes

Je pense que FileHelper essaie d'en faire trop en une seule fois. L'analyse des fichiers est un processus en deux étapes où vous divisez d'abord les lignes en champs, puis vous analysez les champs en données. En combinant les fonctions, il est difficile de gérer des choses comme le filtrage maître-détail et ligne.

4voto

Stefan Egli Points 11708

Je l'utilise ici :

http://www.codeproject.com/KB/database/GenericParser.aspx

La dernière fois que j'ai cherché quelque chose comme ça, je l'ai trouvé dans la réponse à cette question. question .

0voto

Lachlan Points 374

Et les expressions régulières ? Vous pourriez utiliser des groupes nommés pour obtenir vos champs dans chaque "ligne", comme dans cet exemple : http://zamov.online.fr/EXHTML/CSharp/CSharp7.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X