Lectura de archivos CSV y almacenamiento de valores en una matriz

317

Estoy tratando de leer un *.csvarchivo.

El *.csvarchivo consta de dos columnas separadas por punto y coma (" ; ").

Puedo leer el *.csvarchivo usando StreamReader y puedo separar cada línea usando la Split()función. Quiero almacenar cada columna en una matriz separada y luego mostrarla.

¿Es posible hacer eso?

Rushabh Shah
fuente
2
@Marc: desafortunadamente en las culturas que no son inglesas (p. Ej., Italiano) cuando guarda un Excel en CSV que usa ";"como separador ... esto ha hecho de CSV una imo no estándar :(
digEmAll
25
Siempre leo CSV como valores separados por caracteres, ya que las personas llaman archivos CSV incluso si no usan una coma como separador. Y hay tantos dialectos con diferentes citas o reglas de escape en la práctica que realmente no se puede hablar de un estándar, incluso si en teoría hay un RFC.
CodesInChaos
1
El nombre de la extensión del archivo CSV ahora debería cambiar a DSV - Archivo de valores separados delimitador
Ambuj
Para todas las respuestas que simplemente dividen la cadena en el carácter delimitador, esta no es la mejor manera de hacerlo. Hay más reglas para el formato CSV que esto no cubrirá. Es mejor usar un analizador de terceros. Más información- dotnetcoretutorials.com/2018/08/04/csv-parsing-in-net-core
iliketocode

Respuestas:

415

Puedes hacerlo así:

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.
fuente
55
Gracias por esto, había olvidado cómo dividir líneas en un archivo csv (¡tonto!) Pero su solución me ayudó :)
Hallaghan
44
Han pasado más de 3 años y esta pregunta sigue ayudando a alguien. Me siento mal de que no hayas aceptado esto.
AdamMc331
12
No maneja valores de campo con comas, etc.
Mike
12
En caso de utilizar una usingcláusula de aquí, o por lo menos de forma manual Close()el readerya que es un IDisposiblerecurso.
Assaf Israel
30
Esto tampoco analizará correctamente un CSV escrito como column1;"Special ; char in string";column3- tools.ietf.org/html/rfc4180
Ole K
173

Mi analizador CSV favorito es uno integrado en la biblioteca .NET. Este es un tesoro escondido dentro del espacio de nombres Microsoft.VisualBasic. A continuación se muestra un código de muestra:

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

Recuerde agregar referencia a Microsoft.VisualBasic

Aquí encontrará más detalles sobre el analizador: http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html

Habeeb
fuente
66
Me gusta esta opción lo mejor. No tengo que preocuparme por los caracteres de escape ya que la clase es un analizador CSV y no algo que se construya manualmente.
Timothy Gonzalez el
22
En caso de que alguien se encuentre con esto y se pregunte, deberá incluir la referencia al Microsoft.VisualBasicensamblaje del marco, ya que generalmente no se hace referencia de forma predeterminada.
apokryfos
3
Desearía haber recordado esto de mis días VB6, me habría ahorrado mucho tiempo a lo largo de los años. Si bien algunos protestarán por VB, no tengo problemas para agregar el dll & namespace a mi código si tiene valor. Esto tiene MUCHO valor.
Walter
2
Esta solución es un jonrón. analizador muy confiable desde mi experiencia.
Glenn Ferrie
3
¿Por qué solo en VB dll?
Mark Choi
75

Forma LINQ:

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

^^ Incorrecto - Editar por Nick

Parece que el respondedor original estaba intentando poblar csvcon una matriz bidimensional, una matriz que contiene matrices. Cada elemento en la primera matriz contiene una matriz que representa ese número de línea con cada elemento en la matriz anidada que contiene los datos para esa columna específica.

var csv = from line in lines
          select (line.Split(',')).ToArray();
as-cii
fuente
2
Tal vez me falta algo, pero no estoy seguro de cuál es el punto de su variable csv: ¿no está simplemente recreando la misma estructura de datos que ya está en líneas?
Ben Hughes
13
@ClayShannon .NET 1.1? Lo siento mucho por ti.
contactmatt
55
@contactmatt: no te desacreditaré de ese sentimiento.
B. Clay Shannon
99
También quiero señalar que los csv se pueden citar ... Entonces, usar string.Split no es una opción viable.
Alxandr
55
Estoy obteniendo: 'System.Array' no contiene una definición para 'Split' y no se puede encontrar ningún método de extensión 'Split' que acepte un primer argumento de tipo 'System.Array' (¿falta una directiva de uso o una referencia de ensamblado? ?)
Kala J
36

No puede crear una matriz de inmediato porque necesita saber el número de filas desde el principio (y esto requeriría leer el archivo csv dos veces)

Puedes almacenar valores en dos List<T> y luego usarlos o convertirlos en una matriz usandoList<T>.ToArray()

Ejemplo muy 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);

nótese bien

Tenga en cuenta que este es solo un ejemplo muy simple . El uso string.Splitno tiene en cuenta los casos en que algunos registros contienen el separador ;en su interior.
Para un enfoque más seguro, considere usar algunas bibliotecas específicas de csv como CsvHelper en nuget.

digEmAll
fuente
No tiene en cuenta ;ser parte del valor, por ejemplo "value with ; inside it". Valores envolventes CSV que contienen caracteres especiales con comillas dobles para decir que es una cadena literal.
ChickenFeet
1
@ChickenFeet: claro, esa es la razón del subtítulo: "Ejemplo muy simple" . De todos modos, puedo agregar una nota al respecto;)
digEmAll
No se preocupe, noté muchas otras respuestas aquí también no lo explican :)
ChickenFeet
1
Regex.Split (sr.ReadLine (), ", (? = (?: [^ \"] * \ "[^ \"] * \ ") * [^ \"] * $) "); // Encontrado esto en SO ... más rápido que una biblioteca.
una pizca
34

Acabo de encontrar esta biblioteca: https://github.com/JoshClose/CsvHelper

Muy intuitivo y fácil de usar. También tiene un paquete nuget que se implementó rápidamente: http://nuget.org/packages/CsvHelper/1.17.0 . También parece mantenerse activamente, lo que me gusta.

Configurarlo para usar un punto y coma es fácil: https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations

joshb
fuente
3
¡Esta es la mejor respuesta! Biblioteca robusta que es fácil de colocar y rodar.
Tyler Forsythe
3
La biblioteca CsvHelper es fantástica. Súper rápido y fácil de usar.
Steve Parish
3
Si está buscando una biblioteca que pueda manejar todos los aspectos del formato csv, incluidas las cadenas entre comillas, use esta. ¡Increíble!
Matt
Thx, biblioteca realmente agradable, fácil de usar y muy robusta.
Sebastián Guerrero
2
¿Cómo se compara el rendimiento con Microsoft.VisualBasic.FileIO.TextFieldParser(véase la respuesta de @ Habeeb)?
Bovender
33

Usualmente uso este analizador de codeproject , ya que hay un montón de escapes de caracteres y similares que maneja para mí.

Pablo
fuente
2
Esto es muy bueno y rápido. Si se encuentra en una situación comercial y necesita un crack, use esto.
gjvdkamp
8
Este analizador está disponible en la galería Nuget como LumenWorks.Framework.IO, en caso de que no desee registrarse en CodeProject para descargarlo.
Greg McCoy
30

Aquí está mi variación de la respuesta más votada:

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

La csvvariable se puede usar como en el siguiente ejemplo:

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
fuente
¿Cómo se accede a las filas y columnas en la variable csv?
Matthew Lock
1
¿Cómo manejas la coma de escape?
Kuangwei Zhang
No maneja comas dentro de las columnas. Mejor usar la robusta biblioteca CsvHelper según la respuesta
Tim Partridge
11

Si necesita omitir (encabezado) líneas y / o columnas, puede usar esto para crear una matriz bidimensional:

    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

Esto es bastante útil si necesita dar forma a los datos antes de procesarlos más adelante (suponiendo que las primeras 2 líneas consisten en el título, y la primera columna es un título de fila, que no necesita tener en la matriz porque simplemente querer considerar los datos).

Nota : puede obtener fácilmente los titulares y la primera columna utilizando el siguiente código:

    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

Este código de ejemplo supone la siguiente estructura de su *.csvarchivo:

Matriz CSV

Nota: Si necesita omitir filas vacías, lo que a veces puede ser útil, puede hacerlo insertando

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

entre el fromy la selectdeclaración en los ejemplos de código LINQ anteriores.

Mate
fuente
10

Puede usar Microsoft.VisualBasic.FileIO.TextFieldParser dll en C # para un mejor rendimiento

obtener el siguiente ejemplo de código del artículo anterior

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
fuente
99
No es tan eficiente porque Split no hace todo lo que hace TextFieldParser. Por ejemplo, omita las líneas de comentarios, maneje los campos entre comillas y elimine los espacios en blanco iniciales / finales. No es exactamente una comparación 1: 1.
Robert McKee
5

Hola a todos, creé una clase estática para hacer esto. + verificación de columna + eliminación de signo de cuota

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
fuente
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
fuente
Gracias por tu ayuda. Podría ayudar a resolver mi problema. En realidad, tengo que leer los datos del archivo y luego insertarlos en la base de datos. En el momento de la inserción, recibo un error de restricción de clave principal (ya que tengo datos en la base de datos). Entonces, necesito programar de tal manera que con la variable ya exista y luego actualizar los datos.
Rushabh Shah
Supongo que el primer valor es PK: debe obtener un registro por id de la base de datos y, si existe, emitir una declaración UPDATE, de lo contrario, inserte un nuevo registro.
Jakub Konecki
3

Aquí hay un caso especial donde uno de los campos de datos tiene punto y coma (";") como parte de sus datos en ese caso, la mayoría de las respuestas anteriores fallarán.

Solución si ese caso será

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
fuente
2

La biblioteca de código abierto Angara.Table permite cargar CSV en columnas escritas, para que pueda obtener los arreglos de las columnas. Cada columna puede indexarse ​​tanto por nombre como por índice. Ver http://predictionmachines.github.io/Angara.Table/saveload.html .

La biblioteca sigue RFC4180 para CSV; Permite la inferencia de tipos y cadenas multilínea.

Ejemplo:

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

Puede ver un tipo de columna utilizando el tipo Columna, p. Ej.

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

Dado que la biblioteca se centra en F #, es posible que deba agregar una referencia al ensamblaje FSharp.Core 4.4; haga clic en 'Agregar referencia' en el proyecto y elija FSharp.Core 4.4 en "Ensamblados" -> "Extensiones".

Dmitry Voytsekhovskiy
fuente
2

He pasado algunas horas buscando una biblioteca adecuada, pero finalmente escribí mi propio código :) Puedes leer el archivo (o base de datos) con las herramientas que quieras y luego aplicar la siguiente rutina a cada línea:

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
fuente
1

He estado usando csvreader.com (componente pago) durante años, y nunca he tenido un problema. Es sólido, pequeño y rápido, pero hay que pagarlo. Puede configurar el delimitador a lo que quiera.

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
fuente
1

Solo soy un estudiante que trabaja en mi tesis de maestría, pero esta es la forma en que la resolví y funcionó bien para mí. Primero selecciona su archivo del directorio (solo en formato csv) y luego coloca los datos en las listas.

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
fuente
0

Sigue siendo incorrecto. Necesita compensar "" entre comillas. Aquí está mi solución Microsoft style csv.

               /// <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
fuente
3
No maneja el caso cuando hay nuevas líneas dentro de los valores de las columnas;)
Emil
0

Tengo una biblioteca que está haciendo exactamente lo que necesitas.

Hace algún tiempo escribí una biblioteca lo suficientemente simple y rápida para trabajar con archivos CSV. Puede encontrarlo en el siguiente enlace: https://github.com/ukushu/DataExporter

Funciona con CSV como con matriz de 2 dimensiones. Exactamente como lo necesitas.

Como ejemplo, en caso de que necesite todos los valores de la tercera fila, solo necesita escribir:

Csv csv = new Csv();

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

var allValuesOf3rdRow = csv.Rows[2];

o para leer la segunda celda de

var value = csv.Rows[2][1];
Andrés
fuente
-1

mira este

usando CsvFramework;

usando System.Collections.Generic;

espacio de nombres 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
fuente