CSV Les importations de fichiers en .Net

voix
99

Je sais que c'est une question débutant, mais je suis à la recherche d'une solution simple - il semble qu'il devrait y avoir un.

Quelle est la meilleure façon d'importer un fichier CSV dans une structure de données fortement typé? Encore une fois simples = mieux.

Créé 05/08/2008 à 05:43
source utilisateur
Dans d'autres langues...                            


12 réponses

voix
72

Microsoft TextFieldParser est stable et suit la RFC 4180 pour les fichiers CSV. Ne vous laissez pas rebuter par l' Microsoft.VisualBasicespace de noms; il est un composant standard dans le .NET Framework, ajoutez simplement une référence à l'échelle mondiale l' Microsoft.VisualBasicensemble.

Si vous compilez pour Windows (par opposition à Mono) et ne prévoit pas avoir à analyser « cassé » (non-RFC compatible) des fichiers CSV, alors ce serait le choix évident, car il est libre, sans restriction, stable, et soutenu activement, dont la plupart ne peut pas dire pour FileHelpers.

Voir aussi: Comment: lire des-Délimité texte Comma fichiers dans Visual Basic pour un exemple de code VB.

Créé 01/04/2009 à 20:58
source utilisateur

voix
48

Consultez FileHelpers Bibliothèque Open Source .

Créé 05/08/2008 à 05:47
source utilisateur

voix
21

Utiliser une connexion OleDB.

String sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\InputDirectory\\;Extended Properties='text;HDR=Yes;FMT=Delimited'";
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
DataTable dt = new DataTable();
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM file.csv", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
objAdapter1.Fill(dt);
objConn.Close();
Créé 05/11/2008 à 15:41
source utilisateur

voix
12

Si vous vous attendez à des scénarios assez complexes pour l' analyse CSV, ne pensez même pas de rouler notre propre analyseur . Il y a beaucoup d'excellents outils là - bas, comme FileHelpers , ou même ceux de CodeProject .

Le point est un problème assez commun et vous pouvez parier que beaucoup de développeurs de logiciels ont déjà pensé et résolu ce problème.

Créé 17/08/2008 à 00:44
source utilisateur

voix
9

Je suis d' accord avec @ NotMyself . FileHelpers est bien testé et gère toutes sortes de cas de pointe que vous aurez finalement à traiter si vous le faites vous - même. Jetez un oeil à ce que FileHelpers ne et écrire que vous - même si vous êtes absolument sûr que ce soit (1) , vous aurez jamais besoin de gérer les cas limites FileHelpers fait, ou (2) vous aimez écrire ce genre de choses et allez être fou de joie quand vous devez analyser des choses comme ceci:

1, "Bill", "Smith", "superviseur", "Pas de commentaire"

2, 'Drake,', 'O'Malley', "Janitor,

Oops, je ne suis pas cité et je suis sur une nouvelle ligne!

Créé 17/08/2008 à 00:53
source utilisateur

voix
9

Brian donne une bonne solution pour convertir à une collection fortement typé.

La plupart des méthodes d'analyse syntaxique CSV données ne tiennent pas compte des champs ou s'échapper quelques-unes des autres subtilités des fichiers CSV (champs comme Rogner). Voici le code que j'utilise personnellement. Il est un peu rugueux autour des bords et a à peu près pas de rapport d'erreur.

public static IList<IList<string>> Parse(string content)
{
    IList<IList<string>> records = new List<IList<string>>();

    StringReader stringReader = new StringReader(content);

    bool inQoutedString = false;
    IList<string> record = new List<string>();
    StringBuilder fieldBuilder = new StringBuilder();
    while (stringReader.Peek() != -1)
    {
        char readChar = (char)stringReader.Read();

        if (readChar == '\n' || (readChar == '\r' && stringReader.Peek() == '\n'))
        {
            // If it's a \r\n combo consume the \n part and throw it away.
            if (readChar == '\r')
            {
                stringReader.Read();
            }

            if (inQoutedString)
            {
                if (readChar == '\r')
                {
                    fieldBuilder.Append('\r');
                }
                fieldBuilder.Append('\n');
            }
            else
            {
                record.Add(fieldBuilder.ToString().TrimEnd());
                fieldBuilder = new StringBuilder();

                records.Add(record);
                record = new List<string>();

                inQoutedString = false;
            }
        }
        else if (fieldBuilder.Length == 0 && !inQoutedString)
        {
            if (char.IsWhiteSpace(readChar))
            {
                // Ignore leading whitespace
            }
            else if (readChar == '"')
            {
                inQoutedString = true;
            }
            else if (readChar == ',')
            {
                record.Add(fieldBuilder.ToString().TrimEnd());
                fieldBuilder = new StringBuilder();
            }
            else
            {
                fieldBuilder.Append(readChar);
            }
        }
        else if (readChar == ',')
        {
            if (inQoutedString)
            {
                fieldBuilder.Append(',');
            }
            else
            {
                record.Add(fieldBuilder.ToString().TrimEnd());
                fieldBuilder = new StringBuilder();
            }
        }
        else if (readChar == '"')
        {
            if (inQoutedString)
            {
                if (stringReader.Peek() == '"')
                {
                    stringReader.Read();
                    fieldBuilder.Append('"');
                }
                else
                {
                    inQoutedString = false;
                }
            }
            else
            {
                fieldBuilder.Append(readChar);
            }
        }
        else
        {
            fieldBuilder.Append(readChar);
        }
    }
    record.Add(fieldBuilder.ToString().TrimEnd());
    records.Add(record);

    return records;
}

Notez que cela ne gère pas le cas de bord des champs ne sont pas deliminated par des guillemets doubles, mais meerley ayant une chaîne entre guillemets à l' intérieur de celui - ci. Voir ce poste pour un peu mieux expanation, ainsi que des liens vers certaines bibliothèques appropriées.

Créé 08/08/2008 à 17:20
source utilisateur

voix
6

Je me suis ennuyé donc je modifié quelques trucs que j'ai écrit. Il va essayer de résumer l'analyse syntaxique de manière OO whle réduisant la quantité d'itérations dans le fichier, il ne itère une fois au sommet foreach.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {

            // usage:

            // note this wont run as getting streams is not Implemented

            // but will get you started

            CSVFileParser fileParser = new CSVFileParser();

            // TO Do:  configure fileparser

            PersonParser personParser = new PersonParser(fileParser);

            List<Person> persons = new List<Person>();
            // if the file is large and there is a good way to limit
            // without having to reparse the whole file you can use a 
            // linq query if you desire
            foreach (Person person in personParser.GetPersons())
            {
                persons.Add(person);
            }

            // now we have a list of Person objects
        }
    }

    public abstract  class CSVParser 
    {

        protected String[] deliniators = { "," };

        protected internal IEnumerable<String[]> GetRecords()
        {

            Stream stream = GetStream();
            StreamReader reader = new StreamReader(stream);

            String[] aRecord;
            while (!reader.EndOfStream)
            {
                  aRecord = reader.ReadLine().Split(deliniators,
                   StringSplitOptions.None);

                yield return aRecord;
            }

        }

        protected abstract Stream GetStream(); 

    }

    public class CSVFileParser : CSVParser
    {
        // to do: add logic to get a stream from a file

        protected override Stream GetStream()
        {
            throw new NotImplementedException();
        } 
    }

    public class CSVWebParser : CSVParser
    {
        // to do: add logic to get a stream from a web request

        protected override Stream GetStream()
        {
            throw new NotImplementedException();
        }
    }

    public class Person
    {
        public String Name { get; set; }
        public String Address { get; set; }
        public DateTime DOB { get; set; }
    }

    public class PersonParser 
    {

        public PersonParser(CSVParser parser)
        {
            this.Parser = parser;
        }

        public CSVParser Parser { get; set; }

        public  IEnumerable<Person> GetPersons()
        {
            foreach (String[] record in this.Parser.GetRecords())
            {
                yield return new Person()
                {
                    Name = record[0],
                    Address = record[1],
                    DOB = DateTime.Parse(record[2]),
                };
            }
        }
    }
}
Créé 08/08/2008 à 10:39
source utilisateur

voix
5

Il y a deux articles sur CodeProject qui fournissent le code pour une solution, qui utilise StreamReader et qui importe des données CSV à l' aide du pilote de texte Microsoft .

Créé 05/08/2008 à 06:24
source utilisateur

voix
2

Une bonne façon simple de le faire est d'ouvrir le fichier, et lire chaque ligne dans un tableau, liste chaînée, structure de données-de-votre-choix. Soyez prudent sur la manipulation de la première ligne bien.

Cela peut être au- dessus de votre tête, mais il semble y avoir un moyen direct pour y accéder et en utilisant une chaîne de connexion .

Pourquoi ne pas essayer d'utiliser Python au lieu de C # ou VB? Il dispose d'un joli module CSV pour importation qui fait tout le levage lourd pour vous.

Créé 05/08/2008 à 05:49
source utilisateur

voix
1

Je tapais dans un code. Le résultat de la datagridviewer avait l'air bien. Il analyse une seule ligne de texte à un ArrayList d'objets.

    enum quotestatus
    {
        none,
        firstquote,
        secondquote
    }
    public static System.Collections.ArrayList Parse(string line,string delimiter)
    {        
        System.Collections.ArrayList ar = new System.Collections.ArrayList();
        StringBuilder field = new StringBuilder();
        quotestatus status = quotestatus.none;
        foreach (char ch in line.ToCharArray())
        {                                
            string chOmsch = "char";
            if (ch == Convert.ToChar(delimiter))
            {
                if (status== quotestatus.firstquote)
                {
                    chOmsch = "char";
                }                         
                else
                {
                    chOmsch = "delimiter";                    
                }                    
            }

            if (ch == Convert.ToChar(34))
            {
                chOmsch = "quotes";           
                if (status == quotestatus.firstquote)
                {
                    status = quotestatus.secondquote;
                }
                if (status == quotestatus.none )
                {
                    status = quotestatus.firstquote;
                }
            }

            switch (chOmsch)
            {
                case "char":
                    field.Append(ch);
                    break;
                case "delimiter":                        
                    ar.Add(field.ToString());
                    field.Clear();
                    break;
                case "quotes":
                    if (status==quotestatus.firstquote)
                    {
                        field.Clear();                            
                    }
                    if (status== quotestatus.secondquote)
                    {                                                                           
                            status =quotestatus.none;                                
                    }                    
                    break;
            }
        }
        if (field.Length != 0)            
        {
            ar.Add(field.ToString());                
        }           
        return ar;
    }
Créé 09/09/2011 à 11:02
source utilisateur

voix
1

Je devais utiliser un analyseur CSV dans .NET pour un projet cet été et se sont installés sur le pilote de texte Microsoft Jet. Vous spécifiez un dossier à l'aide d'une chaîne de connexion, puis interroger un fichier à l'aide d'une instruction SQL Select. Vous pouvez spécifier les types forts en utilisant un fichier schema.ini. Je ne le fais pas au début, mais je recevais de mauvais résultats où le nombre type de données n'a pas été immédiatement apparente, comme IP ou une entrée comme « XYQ 3.9 SP1 ».

Une limitation je suis tombé est qu'il ne peut pas gérer les noms de colonne au-dessus de 64 caractères; il tronque. Cela ne devrait pas être un problème, sauf que je traitais avec des données d'entrée très mal conçus. Il retourne un DataSet ADO.NET.

Ce fut la meilleure solution que je trouve. Je me méfie de rouler mon propre analyseur CSV, depuis que je ne serais probablement manquer quelques-uns des cas de fin, et je n'ai pas trouvé d'autres paquets d'analyse syntaxique CSV gratuit pour .NET là-bas.

EDIT: En outre, il ne peut y avoir un seul fichier schema.ini par répertoire, donc je dynamiquement ajouté à à typer les colonnes nécessaires. Il ne fortement taper les colonnes spécifiées, et en déduire pour tout champ non précisé. J'ai vraiment apprécié, comme je traitais l'importation d'un fichier CSV de colonne 70+ fluide et ne voulais pas spécifier chaque colonne, seuls ceux de mauvaise conduite.

Créé 16/08/2008 à 23:15
source utilisateur

voix
0

Si vous ne pouvez garantir qu'il n'y a pas de virgules dans les données, puis probablement la façon la plus simple d'utiliser String.split .

Par exemple:

String[] values = myString.Split(',');
myObject.StringField = values[0];
myObject.IntField = Int32.Parse(values[1]);

Il peut y avoir des bibliothèques que vous pouvez utiliser pour aider, mais c'est probablement aussi simple que vous pouvez obtenir. Assurez-vous que vous ne pouvez pas avoir des virgules dans les données, sinon vous devrez analyser mieux.

Créé 05/08/2008 à 06:02
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more