CSV-Datei-Import in .Net

stimmen
99

Ich weiß, das ein Neuling Frage, aber ich bin auf der Suche nach einer einfachen Lösung - es scheint, wie sollte es sein.

Was ist der beste Weg, um eine CSV-Datei in eine stark typisierte Datenstruktur zu importieren? Wieder einfach = besser.

Veröffentlicht am 05/08/2008 um 05:43
quelle vom benutzer
In anderen Sprachen...                            


12 antworten

stimmen
72

Microsofts TextFieldParser ist stabil und folgt RFC 4180 für CSV - Dateien. Lass dich nicht von dem beirren Microsoft.VisualBasicNamespace; es ist eine Standardkomponente in .NET Framework, nur einen Verweis auf die globale hinzufügen Microsoft.VisualBasicMontag.

Wenn Sie für Windows sind Kompilieren (im Gegensatz zu Mono Gegensatz) und gehen nicht davon aus, die „broken“ (nicht-RFC-konform) CSV-Dateien zu analysieren, dann wäre dies die erste Wahl sein, da es frei ist, uneingeschränkte, stabil, und aktiv unterstützt, von denen die meisten nicht für FileHelpers gesagt werden.

Siehe auch: Gewußt wie: Lesen aus durch Kommas getrennte Textdateien in Visual Basic für ein VB - Codebeispiel.

Beantwortet am 01/04/2009 um 20:58
quelle vom benutzer

stimmen
48

Schauen Sie sich FileHelpers Open Source - Bibliothek .

Beantwortet am 05/08/2008 um 05:47
quelle vom benutzer

stimmen
21

Verwenden Sie eine OLEDB-Verbindung.

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();
Beantwortet am 05/11/2008 um 15:41
quelle vom benutzer

stimmen
12

Wenn Sie ziemlich komplexe Szenarien für die CSV - Analyse erwartet, denken Sie nicht einmal auf unsere eigenen Parser von Fahrzeugen . Es gibt viele hervorragende Werkzeuge gibt, wie FileHelpers , oder auch solche , von Codeproject .

Der Punkt ist ein recht häufiges Problem ist , und man konnte darauf wetten , dass eine Menge von Software - Entwicklern bereits gedacht hat und dieses Problem gelöst.

Beantwortet am 17/08/2008 um 00:44
quelle vom benutzer

stimmen
9

Ich stimme mit @ NotMyself .FileHelpers ist gut getestet und kümmert sich um alle Arten von Grenzfällen , die Sie schließlich behandeln werden, wenn Sie es selbst tun. Werfen Sie einen Blick auf das, was FileHelpers hat und nur Ihre eigenen schreiben , wenn Sie absolut sicher sind , dass entweder (1) Sie werden nie die Grenzfälle FileHelpers behandeln müssen der Fall ist, oder (2) Sie gerne schreiben diese Art von Sachen und gehen zu überglücklich sein , wenn Sie Sachen wie diese zu analysieren haben:

1, "Bill", "Smith", "Supervisor", "No Comment"

2 'Drake,', 'O'Malley', "Hausmeister,

Oops, ich bin nicht in Anführungszeichen gesetzt und ich bin auf eine neue Zeile!

Beantwortet am 17/08/2008 um 00:53
quelle vom benutzer

stimmen
9

Brian gibt eine schöne Lösung, die es zu einer stark typisierte Auflistung für die Umwandlung.

Die meisten der Parsing-Methoden CSV gegeben nehmen Sie nicht in Betracht zu entkommen Felder oder einige der anderen Feinheiten von CSV-Dateien (wie Beschneiden Felder). Hier ist der Code, den ich persönlich benutze. Es ist ein wenig rau an den Rändern und hat so ziemlich keine Fehlerberichterstattung.

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;
}

Beachten Sie, dass dies nicht den Rand Fall von Feldern behandelt nicht durch doppelte Anführungszeichen deliminated werden, aber meerley in der es eine Zeichenfolge in Anführungszeichen mit. Sehen Sie diesen Beitrag für ein bisschen besser expanation sowie einige Links zu einigen richtigen Bibliotheken.

Beantwortet am 08/08/2008 um 17:20
quelle vom benutzer

stimmen
6

Ich war langweilig, so dass ich ein paar Sachen geändert i geschrieben. Es versucht, die die Analyse in einer OO-Weise einzukapseln whle auf die Menge von Iterationen durch die Datei Abholzen, ist es nur eine Iteration einmal an der Spitze 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]),
                };
            }
        }
    }
}
Beantwortet am 08/08/2008 um 10:39
quelle vom benutzer

stimmen
5

Es gibt zwei Artikel über Codeproject, der Code für eine Lösung zu bieten, eine , die verwendet Stream und eine , die CSV - Daten importiert mit dem Microsoft Text Driver .

Beantwortet am 05/08/2008 um 06:24
quelle vom benutzer

stimmen
2

Eine gute einfache Möglichkeit, es zu tun ist, um die Datei zu öffnen, und jede Zeile in ein Array lesen, verknüpfte Liste, Datenstruktur-of-your-Wahl. Seien Sie vorsichtig, wenn Sie die erste Zeile der Handhabung.

Dies kann über den Kopf, aber es scheint einen direkten Weg zu sein , sie eine Verwendung als auch für den Zugriff auf Verbindungszeichenfolge .

Warum nicht versuchen, Python anstelle von C # oder VB? Es hat ein schönes CSV-Modul zu importieren, die für Sie all schweres Heben tut.

Beantwortet am 05/08/2008 um 05:49
quelle vom benutzer

stimmen
1

Ich tippte in einigen Code. Das Ergebnis im datagridviewer sah gut aus. Es analysiert eine einzige Zeile Text zu einer Arraylist von Objekten.

    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;
    }
Beantwortet am 09/09/2011 um 11:02
quelle vom benutzer

stimmen
1

Ich hatte in diesem Sommer für ein Projekt eine CSV-Parser in .NET zu verwenden, und ließ sich auf der Microsoft Jet Text Driver. Sie geben einen Ordner, der eine Verbindungszeichenfolge, dann eine Datei abfragen, um eine SQL-Select-Anweisung. Sie können starke Typen geben Sie eine schema.ini-Datei. Ich tat dies nicht auf den ersten, aber dann war ich schlechte Ergebnisse zu erzielen, wenn die Art der Daten war nicht sofort ersichtlich, wie IP-Nummern oder einen Eintrag wie „XYQ 3.9 SP1“.

Eine Einschränkung Ich lief in ist, dass es keine Spaltennamen über 64 Zeichen verarbeiten kann; es kürzt. Dies sollte kein Problem sein, außer ich sehr schlecht gestaltete Eingangsdaten zu tun war. Es gibt einen ADO.NET DataSet.

Dies war die beste Lösung, die ich gefunden. Ich würde vorsichtig sein, meine eigenen CSV-Parser von Rollen, da ich wahrscheinlich einige der End-Fälle vermissen würde, und ich habe keine anderen freien CSV-Parsing-Pakete für .NET da draußen finden.

EDIT: Auch kann es nur sein, eine Datei schema.ini pro Verzeichnis, so dass ich dynamisch angehängt zu stark den benötigten Spalten eingeben. Es wird nur stark geben Sie die Spalten angegeben, und für eine beliebige nicht spezifizierte Feld schließen. Ich wirklich dieses geschätzt, wie ich es zu tun hatte eine Flüssigkeit 70+ Spalte CSV Import und wollen nicht jede Spalte angeben, nur die abgestürzten diejenigen.

Beantwortet am 16/08/2008 um 23:15
quelle vom benutzer

stimmen
0

Wenn Sie garantieren können , dass es keine Kommas in den Daten sind, dann wäre der einfachste Weg , wahrscheinlich zu verwenden String.split .

Beispielsweise:

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

Es können Bibliotheken sein, Ihnen zu helfen nutzen könnten, aber das ist wahrscheinlich so einfach, wie Sie bekommen können. So stellen Sie sicher, dass Sie keine Kommas in den Daten haben kann, sonst müssen Sie analysieren, es besser.

Beantwortet am 05/08/2008 um 06:02
quelle vom benutzer

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