Lecture d'un fichier CSV et stockage de valeurs dans un tableau

317

J'essaie de lire un *.csvfichier.

Le *.csvfichier -f se compose de deux colonnes séparées par un point-virgule (" ; ").

Je suis capable de lire le *.csvfichier en utilisant StreamReader et de séparer chaque ligne en utilisant la Split()fonction. Je souhaite stocker chaque colonne dans un tableau séparé, puis l'afficher.

Est-il possible de faire ça?

Rushabh Shah
la source
2
@Marc: malheureusement dans les cultures non anglaises (par exemple l'italien) lorsque vous enregistrez un fichier Excel au format CSV qu'il utilise ";"comme séparateur ... cela a fait du CSV un imo non standard :(
digEmAll
25
Je lis toujours CSV comme des valeurs séparées par des caractères car les gens appellent les fichiers CSV même s'ils n'utilisent pas de virgule comme séparateur. Et il y a tellement de dialectes avec des règles de citation ou d'échappement différentes dans la pratique que vous ne pouvez pas vraiment parler d'une norme même si en théorie il y a un RFC.
CodesInChaos
1
Le nom de l'extension de fichier CSV devrait maintenant être
remplacé par
Pour toutes les réponses qui divisent simplement la chaîne sur le caractère délimiteur, ce n'est pas la meilleure façon de procéder. Il y a plus de règles au format CSV que cela ne couvrira pas. Il est préférable d'utiliser un analyseur tiers. Plus d' infos- dotnetcoretutorials.com/2018/08/04/csv-parsing-in-net-core
iliketocode

Réponses:

416

Vous pouvez le faire comme ceci:

using System.IO;

static void Main(string[] args)
{
    using(var reader = new StreamReader(@"C:\test.csv"))
    {
        List<string> listA = new List<string>();
        List<string> listB = new List<string>();
        while (!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            var values = line.Split(';');

            listA.Add(values[0]);
            listB.Add(values[1]);
        }
    }
}
Michael M.
la source
5
Merci pour cela, j'avais oublié comment diviser des lignes dans un fichier csv (stupide moi!) Mais votre solution m'a aidé :)
Hallaghan
4
C'est plus de 3 ans plus tard et cette question aide toujours quelqu'un. Je me sens mal que vous n'ayez pas été accepté à ce sujet.
AdamMc331
12
Ne gère pas les valeurs de champ avec des virgules, etc.
Mike
12
Vous devez utiliser une usingclause ici, ou à tout le moins manuellement Close()le readercomme il est une IDisposibleressource.
Assaf Israël
30
Cela n'analysera pas non plus correctement un CSV écrit comme column1;"Special ; char in string";column3- tools.ietf.org/html/rfc4180
Ole K
173

Mon analyseur CSV préféré est intégré à la bibliothèque .NET. Il s'agit d'un trésor caché dans l'espace de noms Microsoft.VisualBasic. Voici un exemple de code:

using Microsoft.VisualBasic.FileIO;

var path = @"C:\Person.csv"; // Habeeb, "Dubai Media City, Dubai"
using (TextFieldParser csvParser = new TextFieldParser(path))
{
 csvParser.CommentTokens = new string[] { "#" };
 csvParser.SetDelimiters(new string[] { "," });
 csvParser.HasFieldsEnclosedInQuotes = true;

 // Skip the row with the column names
 csvParser.ReadLine();

 while (!csvParser.EndOfData)
 {
  // Read current line fields, pointer moves to the next line.
  string[] fields = csvParser.ReadFields();
  string Name = fields[0];
  string Address = fields[1];
 }
}

N'oubliez pas d'ajouter une référence à Microsoft.VisualBasic

Plus de détails sur l'analyseur sont fournis ici: http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html

Habeeb
la source
6
J'aime le mieux cette option. Je n'ai pas à m'inquiéter des caractères d'échappement car la classe est un analyseur CSV et non quelque chose en cours de construction manuelle.
Timothy Gonzalez
22
Au cas où quelqu'un se heurterait à cela et se poserait la question, vous devrez inclure la référence à l' Microsoft.VisualBasicassembly du framework car il n'est généralement pas référencé par défaut.
apokryfos
3
J'aurais aimé m'en souvenir de mes jours VB6, cela m'aurait fait gagner beaucoup de temps au fil des ans. Alors que certains se déchaînent sur VB, je n'ai aucun problème à ajouter la dll et l'espace de noms à mon code s'il a une valeur. Cela a BEAUCOUP de valeur.
Walter
2
Cette solution est un homerun. analyseur très fiable de mon expérience.
Glenn Ferrie
3
Pourquoi seulement dans VB dll?
Mark Choi
75

Façon LINQ:

var lines = File.ReadAllLines("test.txt").Select(a => a.Split(';'));
var csv = from line in lines
          select (from piece in line
                  select piece);

^^ Wrong - Edit by Nick

Il semble que le répondeur d'origine tentait de remplir csvavec un tableau à 2 dimensions - un tableau contenant des tableaux. Chaque élément du premier tableau contient un tableau représentant ce numéro de ligne, chaque élément du tableau imbriqué contenant les données de cette colonne spécifique.

var csv = from line in lines
          select (line.Split(',')).ToArray();
as-cii
la source
2
Peut-être que je manque quelque chose, mais je ne sais pas à quoi sert votre variable csv - n'êtes-vous pas simplement en train de recréer la même structure de données qui est déjà lue en lignes?
Ben Hughes
13
@ClayShannon .NET 1.1? Je suis ... vraiment désolé pour toi.
contactmatt
5
@contactmatt: Je ne vais pas vous désabuser de ce sentiment.
B. Clay Shannon
9
Je tiens également à souligner que les csv peuvent être cités ... Donc, l'utilisation de string.Split n'est pas une option viable.
Alxandr
5
J'obtiens: 'System.Array' ne contient pas de définition pour 'Split' et aucune méthode d'extension 'Split' n'accepte un premier argument de type 'System.Array' (vous manque une directive using ou une référence d'assembly ?)
Kala J
36

Vous ne pouvez pas créer un tableau immédiatement car vous devez connaître le nombre de lignes depuis le début (et cela nécessiterait de lire le fichier csv deux fois)

Vous pouvez stocker des valeurs dans deux List<T>, puis les utiliser ou les convertir en tableau à l'aideList<T>.ToArray()

Exemple très simple:

var column1 = new List<string>();
var column2 = new List<string>();
using (var rd = new StreamReader("filename.csv"))
{
    while (!rd.EndOfStream)
    {
        var splits = rd.ReadLine().Split(';');
        column1.Add(splits[0]);
        column2.Add(splits[1]);
    }
}
// print column1
Console.WriteLine("Column 1:");
foreach (var element in column1)
    Console.WriteLine(element);

// print column2
Console.WriteLine("Column 2:");
foreach (var element in column2)
    Console.WriteLine(element);

NB

Veuillez noter que ce n'est qu'un exemple très simple . L'utilisation string.Splitne tient pas compte des cas où certains enregistrements contiennent le séparateur à l' ;intérieur.
Pour une approche plus sûre, pensez à utiliser certaines bibliothèques spécifiques csv comme CsvHelper sur nuget.

digEmAll
la source
Ne tient pas compte de ;faire partie de la valeur, par exemple "value with ; inside it". Valeurs surround CSV contenant des caractères spéciaux avec des guillemets pour indiquer qu'il s'agit d'une chaîne littérale.
ChickenFeet
1
@ChickenFeet: bien sûr, c'est la raison de la légende: "Exemple très simple" . Quoi qu'il en soit, je peux ajouter une note à ce sujet;)
digEmAll
Pas de soucis, j'ai remarqué que beaucoup d'autres réponses ici ne tiennent pas compte non plus :)
ChickenFeet
1
Regex.Split (sr.ReadLine (), ", (? = (?: [^ \"] * \ "[^ \"] * \ ") * [^ \"] * $) "); // Trouvé ceci sur SO ... plus vite qu'une bibliothèque.
Pincer
34

Je viens de découvrir cette bibliothèque: https://github.com/JoshClose/CsvHelper

Très intuitif et facile à utiliser. Possède également un paquet nuget qui est rapide à mettre en œuvre: http://nuget.org/packages/CsvHelper/1.17.0 . Semble également être activement maintenu que j'aime.

Le configurer pour utiliser un point-virgule est facile: https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations

joshb
la source
3
C'est la meilleure réponse! Bibliothèque robuste facile à installer et à utiliser.
Tyler Forsythe
3
La bibliothèque CsvHelper est fantastique. Super rapide et facile à utiliser.
Steve Parish du
3
Si vous recherchez une bibliothèque capable de gérer tous les aspects du format csv, y compris les chaînes entre guillemets, utilisez celle-ci. Impressionnant!
Matt
Thx, bibliothèque vraiment sympa, facile à utiliser et très robuste.
Sebastián Guerrero
2
À quoi la performance se compare-t-elle Microsoft.VisualBasic.FileIO.TextFieldParser(cf. réponse de @ Habeeb)?
bovender
33

J'utilise généralement cet analyseur de codeproject , car il y a un tas d'échappements de caractères et similaires qu'il gère pour moi.

Paul
la source
2
cette chose est très bonne et rapide. Si vous êtes dans une situation commerciale et avez besoin de craquer, utilisez-le.
gjvdkamp
8
Cet analyseur est disponible dans la galerie Nuget sous le nom LumenWorks.Framework.IO, au cas où vous ne voudriez pas vous inscrire à CodeProject pour le télécharger.
Greg McCoy
30

Voici ma variation de la réponse la plus votée:

var contents = File.ReadAllText(filename).Split('\n');
var csv = from line in contents
          select line.Split(',').ToArray();

La csvvariable peut ensuite être utilisée comme dans l'exemple suivant:

int headerRows = 5;
foreach (var row in csv.Skip(headerRows)
    .TakeWhile(r => r.Length > 1 && r.Last().Trim().Length > 0))
{
    String zerothColumnValue = row[0]; // leftmost column
    var firstColumnValue = row[1];
}
tomsv
la source
Comment accédez-vous aux lignes et colonnes de la variable csv?
Matthew Lock
1
comment gérez-vous la virgule d'échappement?
Kuangwei Zhang
Ne gère pas les virgules dans les colonnes. Mieux vaut utiliser la bibliothèque robuste CsvHelper selon la réponse
Tim Partridge
11

Si vous devez sauter des lignes et / ou des colonnes (en-tête), vous pouvez l'utiliser pour créer un tableau à deux dimensions:

    var lines = File.ReadAllLines(path).Select(a => a.Split(';'));
    var csv = (from line in lines               
               select (from col in line
               select col).Skip(1).ToArray() // skip the first column
              ).Skip(2).ToArray(); // skip 2 headlines

Ceci est très utile si vous devez façonner les données avant de les traiter davantage (en supposant que les 2 premières lignes sont constituées du titre et que la première colonne est un titre de ligne - que vous n'avez pas besoin d'avoir dans le tableau car vous venez de vouloir considérer les données).

NB Vous pouvez facilement obtenir les titres et la 1ère colonne en utilisant le code suivant:

    var coltitle = (from line in lines 
                    select line.Skip(1).ToArray() // skip 1st column
                   ).Skip(1).Take(1).FirstOrDefault().ToArray(); // take the 2nd row
    var rowtitle = (from line in lines select line[0] // take 1st column
                   ).Skip(2).ToArray(); // skip 2 headlines

Cet exemple de code suppose la structure suivante de votre *.csvfichier:

Matrice CSV

Remarque: Si vous devez ignorer des lignes vides - ce qui peut parfois être utile, vous pouvez le faire en insérant

    where line.Any(a=>!string.IsNullOrWhiteSpace(a))

entre le fromet l' selectinstruction dans les exemples de code LINQ ci-dessus.

Mat
la source
10

Vous pouvez utiliser la DLL Microsoft.VisualBasic.FileIO.TextFieldParser en C # pour de meilleures performances

obtenir ci-dessous l'exemple de code de l'article ci-dessus

static void Main()
{
    string csv_file_path=@"C:\Users\Administrator\Desktop\test.csv";

    DataTable csvData = GetDataTabletFromCSVFile(csv_file_path);

    Console.WriteLine("Rows count:" + csvData.Rows.Count);

    Console.ReadLine();
}


private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
{
    DataTable csvData = new DataTable();

    try
    {

    using(TextFieldParser csvReader = new TextFieldParser(csv_file_path))
        {
            csvReader.SetDelimiters(new string[] { "," });
            csvReader.HasFieldsEnclosedInQuotes = true;
            string[] colFields = csvReader.ReadFields();
            foreach (string column in colFields)
            {
                DataColumn datecolumn = new DataColumn(column);
                datecolumn.AllowDBNull = true;
                csvData.Columns.Add(datecolumn);
            }

            while (!csvReader.EndOfData)
            {
                string[] fieldData = csvReader.ReadFields();
                //Making empty value as null
                for (int i = 0; i < fieldData.Length; i++)
                {
                    if (fieldData[i] == "")
                    {
                        fieldData[i] = null;
                    }
                }
                csvData.Rows.Add(fieldData);
            }
        }
    }
    catch (Exception ex)
    {
    }
    return csvData;
}
kombsh
la source
9
Ce n'est pas aussi efficace car Split ne fait pas tout ce que TextFieldParser fait. Par exemple, ignorez les lignes de commentaire, gérez les champs entre guillemets et supprimez les espaces de début / fin. Pas exactement une comparaison 1: 1.
Robert McKee
5

Salut à tous, j'ai créé une classe statique pour ce faire. + vérification de colonne + suppression de signe de quota

public static class CSV
{
    public static List<string[]> Import(string file, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign)
    {
        return ReadCSVFile(file, csvDelimiter, ignoreHeadline, removeQuoteSign);
    }

    private static List<string[]> ReadCSVFile(string filename, char csvDelimiter, bool ignoreHeadline, bool removeQuoteSign)
    {
        string[] result = new string[0];
        List<string[]> lst = new List<string[]>();

        string line;
        int currentLineNumner = 0;
        int columnCount = 0;

        // Read the file and display it line by line.  
        using (System.IO.StreamReader file = new System.IO.StreamReader(filename))
        {
            while ((line = file.ReadLine()) != null)
            {
                currentLineNumner++;
                string[] strAr = line.Split(csvDelimiter);
                // save column count of dirst line
                if (currentLineNumner == 1)
                {
                    columnCount = strAr.Count();
                }
                else
                {
                    //Check column count of every other lines
                    if (strAr.Count() != columnCount)
                    {
                        throw new Exception(string.Format("CSV Import Exception: Wrong column count in line {0}", currentLineNumner));
                    }
                }

                if (removeQuoteSign) strAr = RemoveQouteSign(strAr);

                if (ignoreHeadline)
                {
                    if(currentLineNumner !=1) lst.Add(strAr);
                }
                else
                {
                    lst.Add(strAr);
                }
            }

        }

        return lst;
    }
    private static string[] RemoveQouteSign(string[] ar)
    {
        for (int i = 0;i< ar.Count() ; i++)
        {
            if (ar[i].StartsWith("\"") || ar[i].StartsWith("'")) ar[i] = ar[i].Substring(1);
            if (ar[i].EndsWith("\"") || ar[i].EndsWith("'")) ar[i] = ar[i].Substring(0,ar[i].Length-1);

        }
        return ar;
    }

}
Mathias Schmidt
la source
4
var firstColumn = new List<string>();
var lastColumn = new List<string>();

// your code for reading CSV file

foreach(var line in file)
{
    var array = line.Split(';');
    firstColumn.Add(array[0]);
    lastColumn.Add(array[1]);
}

var firstArray = firstColumn.ToArray();
var lastArray = lastColumn.ToArray();
Jakub Konecki
la source
Merci de votre aide. Cela pourrait aider à résoudre mon problème. En fait, je dois lire les données du fichier, puis les insérer dans la base de données. Au moment de l'insertion, j'obtiens une erreur de contrainte de clé primaire (car j'ai déjà des données dans la base de données). Donc, je dois programmer de telle sorte que la variable existe déjà, puis mettre à jour les données.
Rushabh Shah
J'assume la première valeur si PK - vous devez obtenir un enregistrement par id de la base de données et s'il existe, émettre une instruction UPDATE, sinon insérer un nouvel enregistrement.
Jakub Konecki
3

Voici un cas spécial où l'un des champs de données a un point-virgule (";") dans le cadre de ses données dans ce cas, la plupart des réponses ci-dessus échouent.

Solution ce cas sera

string[] csvRows = System.IO.File.ReadAllLines(FullyQaulifiedFileName);
string[] fields = null;
List<string> lstFields;
string field;
bool quoteStarted = false;
foreach (string csvRow in csvRows)
{
    lstFields = new List<string>();
    field = "";
    for (int i = 0; i < csvRow.Length; i++)
    {
        string tmp = csvRow.ElementAt(i).ToString();
        if(String.Compare(tmp,"\"")==0)
        {
            quoteStarted = !quoteStarted;
        }
        if (String.Compare(tmp, ";") == 0 && !quoteStarted)
        {
            lstFields.Add(field);
            field = "";
        }
        else if (String.Compare(tmp, "\"") != 0)
        {
            field += tmp;
        }
    }
    if(!string.IsNullOrEmpty(field))
    {
        lstFields.Add(field);
        field = "";
    }
// This will hold values for each column for current row under processing
    fields = lstFields.ToArray(); 
}
Yogesh
la source
2

La bibliothèque open source Angara.Table permet de charger CSV dans des colonnes typées, afin que vous puissiez obtenir les tableaux à partir des colonnes. Chaque colonne peut être indexée à la fois par nom ou par index. Voir http://predictionmachines.github.io/Angara.Table/saveload.html .

La bibliothèque suit RFC4180 pour CSV; il permet l'inférence de type et les chaînes multilignes.

Exemple:

using System.Collections.Immutable;
using Angara.Data;
using Angara.Data.DelimitedFile;

...

ReadSettings settings = new ReadSettings(Delimiter.Semicolon, false, true, null, null);
Table table = Table.Load("data.csv", settings);
ImmutableArray<double> a = table["double-column-name"].Rows.AsReal;

for(int i = 0; i < a.Length; i++)
{
    Console.WriteLine("{0}: {1}", i, a[i]);
}

Vous pouvez voir un type de colonne en utilisant le type Colonne, par exemple

Column c = table["double-column-name"];
Console.WriteLine("Column {0} is double: {1}", c.Name, c.Rows.IsRealColumn);

Étant donné que la bibliothèque se concentre sur F #, vous devrez peut-être ajouter une référence à l'assembly FSharp.Core 4.4; cliquez sur 'Ajouter une référence' sur le projet et choisissez FSharp.Core 4.4 sous "Assemblys" -> "Extensions".

Dmitry Voytsekhovskiy
la source
2

J'ai passé quelques heures à chercher une bonne bibliothèque, mais finalement j'ai écrit mon propre code :) Vous pouvez lire le fichier (ou la base de données) avec les outils que vous voulez, puis appliquer la routine suivante à chaque ligne:

private static string[] SmartSplit(string line, char separator = ',')
{
    var inQuotes = false;
    var token = "";
    var lines = new List<string>();
    for (var i = 0; i < line.Length; i++) {
        var ch = line[i];
        if (inQuotes) // process string in quotes, 
        {
            if (ch == '"') {
                if (i<line.Length-1 && line[i + 1] == '"') {
                    i++;
                    token += '"';
                }
                else inQuotes = false;
            } else token += ch;
        } else {
            if (ch == '"') inQuotes = true;
            else if (ch == separator) {
                lines.Add(token);
                token = "";
                } else token += ch;
            }
    }
    lines.Add(token);
    return lines.ToArray();
}
Zbyszek Swirski
la source
1

J'utilise csvreader.com (composant payant) depuis des années et je n'ai jamais eu de problème. Il est solide, petit et rapide, mais vous devez le payer. Vous pouvez définir le délimiteur à votre guise.

using (CsvReader reader = new CsvReader(s) {
    reader.Settings.Delimiter = ';';
    reader.ReadHeaders();  // if headers on a line by themselves.  Makes reader.Headers[] available
    while (reader.ReadRecord())
        ... use reader.Values[col_i] ...
}
Oliver Bock
la source
1

Je suis juste un étudiant qui travaille sur ma thèse de maîtrise, mais c'est ainsi que je l'ai résolu et cela a bien fonctionné pour moi. Vous sélectionnez d'abord votre fichier dans le répertoire (uniquement au format csv), puis vous mettez les données dans les listes.

List<float> t = new List<float>();
List<float> SensorI = new List<float>();
List<float> SensorII = new List<float>();
List<float> SensorIII = new List<float>();
using (OpenFileDialog dialog = new OpenFileDialog())
{
    try
    {
        dialog.Filter = "csv files (*.csv)|*.csv";
        dialog.Multiselect = false;
        dialog.InitialDirectory = ".";
        dialog.Title = "Select file (only in csv format)";
        if (dialog.ShowDialog() == DialogResult.OK)
        {
            var fs = File.ReadAllLines(dialog.FileName).Select(a => a.Split(';'));
            int counter = 0;
            foreach (var line in fs)
            {
                counter++;
                if (counter > 2)    // Skip first two headder lines
                {
                    this.t.Add(float.Parse(line[0]));
                    this.SensorI.Add(float.Parse(line[1]));
                    this.SensorII.Add(float.Parse(line[2]));
                    this.SensorIII.Add(float.Parse(line[3]));
                }
            }
        }
    }
    catch (Exception exc)
    {
        MessageBox.Show(
            "Error while opening the file.\n" + exc.Message, 
            this.Text, 
            MessageBoxButtons.OK, 
            MessageBoxIcon.Error
        );
    }
}
Daniel
la source
0

Toujours incorrecte. Vous devez compenser "" entre guillemets. Voici ma solution CSV style Microsoft.

               /// <summary>
    /// Microsoft style csv file.  " is the quote character, "" is an escaped quote.
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="sepChar"></param>
    /// <param name="quoteChar"></param>
    /// <param name="escChar"></param>
    /// <returns></returns>
    public static List<string[]> ReadCSVFileMSStyle(string fileName, char sepChar = ',', char quoteChar = '"')
    {
        List<string[]> ret = new List<string[]>();

        string[] csvRows = System.IO.File.ReadAllLines(fileName);

        foreach (string csvRow in csvRows)
        {
            bool inQuotes = false;
            List<string> fields = new List<string>();
            string field = "";
            for (int i = 0; i < csvRow.Length; i++)
            {
                if (inQuotes)
                {
                    // Is it a "" inside quoted area? (escaped litteral quote)
                    if(i < csvRow.Length - 1 && csvRow[i] == quoteChar && csvRow[i+1] == quoteChar)
                    {
                        i++;
                        field += quoteChar;
                    }
                    else if(csvRow[i] == quoteChar)
                    {
                        inQuotes = false;
                    }
                    else
                    {
                        field += csvRow[i];
                    }
                }
                else // Not in quoted region
                {
                     if (csvRow[i] == quoteChar)
                    {
                        inQuotes = true;
                    }
                    if (csvRow[i] == sepChar)
                    {
                        fields.Add(field);
                        field = "";
                    }
                    else 
                    {
                        field += csvRow[i];
                    }
                }
            }
            if (!string.IsNullOrEmpty(field))
            {
                fields.Add(field);
                field = "";
            }
            ret.Add(fields.ToArray());
        }

        return ret;
    }
}
R Keene
la source
3
Il ne gère pas le cas quand il y a des sauts de ligne à l'intérieur des valeurs de colonne;)
Emil
0

J'ai une bibliothèque qui fait exactement ce dont vous avez besoin.

Il y a quelque temps, j'avais écrit une bibliothèque assez simple et rapide pour travailler avec des fichiers CSV. Vous pouvez le trouver par le lien suivant: https://github.com/ukushu/DataExporter

Il fonctionne avec CSV comme avec un tableau à 2 dimensions. Exactement comme vous en avez besoin.

Par exemple, si vous avez besoin de toutes les valeurs de la 3ème ligne, il vous suffit d'écrire:

Csv csv = new Csv();

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

var allValuesOf3rdRow = csv.Rows[2];

ou pour lire la 2e cellule de

var value = csv.Rows[2][1];
Andrew
la source
-1

regarde ça

en utilisant CsvFramework;

using System.Collections.Generic;

espace de noms CvsParser {

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Order> Orders { get; set; }        
}

public class Order
{
    public int Id { get; set; }

    public int CustomerId { get; set; }
    public int Quantity { get; set; }

    public int Amount { get; set; }

    public List<OrderItem> OrderItems { get; set; }

}

public class Address
{
    public int Id { get; set; }
    public int CustomerId { get; set; }

    public string Name { get; set; }
}

public class OrderItem
{
    public int Id { get; set; }
    public int OrderId { get; set; }

    public string ProductName { get; set; }
}

class Program
{
    static void Main(string[] args)
    {

        var customerLines = System.IO.File.ReadAllLines(@"Customers.csv");
        var orderLines = System.IO.File.ReadAllLines(@"Orders.csv");
        var orderItemLines = System.IO.File.ReadAllLines(@"OrderItemLines.csv");

        CsvFactory.Register<Customer>(builder =>
        {
            builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
            builder.Add(a => a.Name).Type(typeof(string)).Index(1);
            builder.AddNavigation(n => n.Orders).RelationKey<Order, int>(k => k.CustomerId);

        }, false, ',', customerLines);

        CsvFactory.Register<Order>(builder =>
        {
            builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
            builder.Add(a => a.CustomerId).Type(typeof(int)).Index(1);
            builder.Add(a => a.Quantity).Type(typeof(int)).Index(2);
            builder.Add(a => a.Amount).Type(typeof(int)).Index(3);
            builder.AddNavigation(n => n.OrderItems).RelationKey<OrderItem, int>(k => k.OrderId);

        }, true, ',', orderLines);


        CsvFactory.Register<OrderItem>(builder =>
        {
            builder.Add(a => a.Id).Type(typeof(int)).Index(0).IsKey(true);
            builder.Add(a => a.OrderId).Type(typeof(int)).Index(1);
            builder.Add(a => a.ProductName).Type(typeof(string)).Index(2);


        }, false, ',', orderItemLines);



        var customers = CsvFactory.Parse<Customer>();


    }
}

}

tobias
la source