web-dev-qa-db-fra.com

Lecteur CSV C # très simple

J'aimerais créer un tableau à partir d'un fichier CSV.

C'est à peu près aussi simple que vous pouvez l'imaginer, le fichier CSV n'aura jamais qu'une seule ligne et ces valeurs:

Device, SignalStrength, Location, Time, Age.

Je voudrais mettre ces valeurs dans un tableau à une dimension.

J'ai essayé quelques exemples, mais ils ont tous été plus compliqués que nécessaire.

37
DNN

S'il n'y a qu'une seule ligne, faites quelque chose comme ceci:

using System;
using System.IO;

class Program
{
    static void Main()
    {
        String[] values = File.ReadAllText(@"d:\test.csv").Split(',');
    }
}
51
Andrew Hare

Vous pouvez essayer quelque chose comme l'extrait LINQ ci-dessous.

string[] allLines = File.ReadAllLines(@"E:\Temp\data.csv");

    var query = from line in allLines
                let data = line.Split(',')
                select new
                {
                    Device = data[0],
                    SignalStrength = data[1],
                    Location = data[2], 
                    Time = data[3],
                    Age = Convert.ToInt16(data[4])
                };

UPDATE: Au fil du temps, les choses ont évolué. À partir de maintenant, je préférerais utiliser cette bibliothèque http://www.aspnetperformance.com/post/LINQ-to-CSV-library.aspx

64
Ramesh

Voici une fonction simple que j'ai faite. Il accepte une chaîne de caractères CSV et renvoie un tableau de champs:

Cela fonctionne bien avec les fichiers CSV générés par Excel et de nombreuses autres variantes.

    public static string[] ParseCsvRow(string r)
    {

        string[] c;
        string t;
        List<string> resp = new List<string>();
        bool cont = false;
        string cs = "";

        c = r.Split(new char[] { ',' }, StringSplitOptions.None);

        foreach (string y in c)
        {
            string x = y;


            if (cont)
            {
                // End of field
                if (x.EndsWith("\""))
                {
                    cs += "," + x.Substring(0, x.Length - 1);
                    resp.Add(cs);
                    cs = "";
                    cont = false;
                    continue;

                }
                else
                {
                    // Field still not ended
                    cs += "," + x;
                    continue;
                }
            }

            // Fully encapsulated with no comma within
            if (x.StartsWith("\"") && x.EndsWith("\""))
            {
                if ((x.EndsWith("\"\"") && !x.EndsWith("\"\"\"")) && x != "\"\"")
                {
                    cont = true;
                    cs = x;
                    continue;
                }

                resp.Add(x.Substring(1, x.Length - 2));
                continue;
            }

            // Start of encapsulation but comma has split it into at least next field
            if (x.StartsWith("\"") && !x.EndsWith("\""))
            {
                cont = true;
                cs += x.Substring(1);
                continue;
            }

            // Non encapsulated complete field
            resp.Add(x);

        }

        return resp.ToArray();

    }
8
Chris Wilson

Cette version corrigée du code ci-dessus rappelle le dernier élément de la ligne CVS ;-)

(testé avec un fichier CSV avec 5400 lignes et 26 éléments par ligne)

   public static string[] CSVRowToStringArray(string r, char fieldSep = ',', char stringSep = '\"')  {
            bool bolQuote = false;
            StringBuilder bld = new StringBuilder();
            List<string> retAry = new List<string>();

            foreach (char c in r.ToCharArray())
                if ((c == fieldSep && !bolQuote))
                {
                    retAry.Add(bld.ToString());
                    bld.Clear();
                }
                else
                    if (c == stringSep)
                        bolQuote = !bolQuote;
                    else
                        bld.Append(c);

            /* to solve the last element problem */
            retAry.Add(bld.ToString()); /* added this line */
            return retAry.ToArray();
        }
4
Paolo D.a

C’est ce que j’ai utilisé dans un projet: analyser une seule ligne de données.

    private string[] csvParser(string csv, char separator = ',')
    {
        List <string> = new <string>();
        string[] temp = csv.Split(separator);
        int counter = 0;
        string data = string.Empty;
        while (counter < temp.Length)
        {
            data = temp[counter].Trim();
            if (data.Trim().StartsWith("\""))
            {
                bool isLast = false;
                while (!isLast && counter < temp.Length)
                {
                    data += separator.ToString() + temp[counter + 1];
                    counter++;
                    isLast = (temp[counter].Trim().EndsWith("\""));
                }
            }
            parsed.Add(data);
            counter++;
        }

        return parsed.ToArray();

    }

http://zamirsblog.blogspot.com/2013/09/c-csv-parser-csvparser.html

3
Zamir

Ma solution gère les guillemets, les séparateurs de champs et de chaînes, etc. Elle est courte et agréable.

    public static string[] CSVRowToStringArray(string r, char fieldSep = ',', char stringSep = '\"')
    {
        bool bolQuote = false;
        StringBuilder bld = new StringBuilder();
        List<string> retAry = new List<string>();

        foreach (char c in r.ToCharArray())
            if ((c == fieldSep && !bolQuote))
            {
                retAry.Add(bld.ToString());
                bld.Clear();
            }
            else
                if (c == stringSep)
                    bolQuote = !bolQuote;
                else
                    bld.Append(c);

        return retAry.ToArray();
    }
2

Tout d'abord besoin de comprendre ce qu'est le CSV et comment l'écrire.

(La plupart des réponses (toutes pour le moment) n'utilisent pas cette exigence, c'est pourquoi elles sont toutes fausses!)

  1. Chaque chaîne suivante (/r/n) est la rangée "table" suivante.
  2. Les cellules "Table" sont séparées par un symbole de délimiteur.
  3. Comme délimiteur peut être utilisé N'IMPORTE QUEL symbole. C'est souvent \t ou ,.
  4. Chaque cellule peut éventuellement contenir ce symbole de délimiteur à l'intérieur de la cellule (la cellule doit commencer par le symbole de guillemets doubles et avoir une double guillemets à la fin dans ce cas)
  5. Chaque cellule peut éventuellement contenir /r/n symboles à l'intérieur de la cellule (la cellule doit commencer par le symbole de guillemets doubles et avoir à la fin un guillemet double à la fin)

Il y a quelque temps, j'avais écrit un cours simple pour la lecture/écriture au format CSV basé sur la norme Microsoft.VisualBasic.FileIO bibliothèque. En utilisant cette classe simple, vous pourrez travailler avec CSV comme avec un tableau à 2 dimensions.

Exemple simple d'utilisation de ma bibliothèque:

Csv csv = new Csv("\t");//delimiter symbol

csv.FileOpen("c:\\file1.csv");

var row1Cell6Value = csv.Rows[0][5];

csv.AddRow("asdf","asdffffff","5")

csv.FileSave("c:\\file2.csv");

Vous pouvez trouver ma classe grâce au lien suivant et étudier comment elle est écrite: https://github.com/ukushu/DataExporter

Ce code de bibliothèque est très rapide au travail et le code source est très court.

PS: Dans le même temps, cette solution ne fonctionnera pas pour l'unité.

PS2: Une autre solution consiste à utiliser la bibliothèque "LINQ-to-CSV". Cela doit aussi bien fonctionner. Mais ce sera plus gros.

0
Andrew