Lendo arquivo CSV e armazenando valores em uma matriz

317

Estou tentando ler um *.csvarquivo.

O *.csvarquivo-consiste em duas colunas separadas por ponto e vírgula (" ; ").

Consigo ler o *.csvarquivo-usando StreamReader e separar cada linha usando a Split()função Eu quero armazenar cada coluna em uma matriz separada e exibi-la.

É possível fazer isso?

Rushabh Shah
fonte
2
@ Marc: infelizmente, em culturas não-inglês (por exemplo italiano) Quando você salva uma excel para CSV ele usa ";"como separador ... isso fez CSV um não-padrão imo :(
digEmAll
25
Eu sempre leio CSV como valores separados por caracteres, pois as pessoas chamam arquivos CSV, mesmo que não usem vírgula como separador. E existem tantos dialetos com diferentes regras de citação ou escape na prática que você realmente não pode falar de um padrão, mesmo que em teoria exista uma RFC.
CodesInChaos 12/03
1
O nome da extensão do arquivo CSV agora deve ser alterado para DSV - Arquivo de Valores Separados por Delimitador
Ambuj
Para todas as respostas que simplesmente dividem a sequência no caractere delimitador, esse não é o melhor caminho a percorrer. Existem mais regras no formato CSV que isso não abordará. É melhor usar um analisador de terceiros. Mais informações- dotnetcoretutorials.com/2018/08/04/csv-parsing-in-net-core
iliketocode

Respostas:

415

Você pode fazer assim:

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.
fonte
5
Obrigado por isso, eu tinha esquecido como linhas de divisão em um arquivo CSV (me mudo!), Mas a sua solução me ajudou :)
Hallaghan
4
Já se passaram mais de três anos e essa pergunta ainda está ajudando alguém. Sinto-me mal por você não ter aceitado isso.
AdamMc331
12
Não lidar com valores de campo com vírgulas, etc.
Mike
12
Deve usar uma usingcláusula aqui, ou pelo menos manualmente Close()o readercomo é um IDisposiblerecurso.
Assaf Israel
30
Isso também não corretamente analisar um CSV escrito como column1;"Special ; char in string";column3- tools.ietf.org/html/rfc4180
Ole K
173

Meu analisador CSV favorito é um construído na biblioteca .NET. Este é um tesouro oculto dentro do namespace Microsoft.VisualBasic. Abaixo está um código de exemplo:

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

Lembre-se de adicionar referência a Microsoft.VisualBasic

Mais detalhes sobre o analisador são fornecidos aqui: http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html

Habeeb
fonte
6
Eu gosto mais dessa opção. Não preciso me preocupar com caracteres de escape, pois a classe é um analisador de CSV e não algo que está sendo construído manualmente.
Timothy Gonzalez
22
Caso alguém se depare com isso e esteja se perguntando, você precisará incluir a referência ao Microsoft.VisualBasicassembly da estrutura, pois normalmente não é referenciado por padrão.
Apokryfos
3
Eu gostaria de ter lembrado que isso nos meus dias no VB6 teria me poupado muito tempo ao longo dos anos. Enquanto alguns vão reclamar sobre o VB, não tenho problema em adicionar a dll & namespace ao meu código, se tiver valor. Isso tem muito valor.
305 Walter Walter
2
Esta solução é uma homerun. analisador muito confiável da minha experiência.
Glenn Ferrie
3
Por que apenas na DLL VB?
Mark Choi
75

Maneira LINQ:

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

^^ Errado - Editar por Nick

Parece que o atendedor original estava tentando preencher csvcom uma matriz bidimensional - uma matriz contendo matrizes. Cada item na primeira matriz contém uma matriz que representa esse número de linha com cada item da matriz aninhada que contém os dados para essa coluna específica.

var csv = from line in lines
          select (line.Split(',')).ToArray();
as-cii
fonte
2
Talvez esteja faltando alguma coisa, mas não tenho certeza de qual é o objetivo da sua variável csv - você não está apenas recriando a mesma estrutura de dados que já está nas linhas?
Ben Hughes
13
@ClayShannon .NET 1.1? Sinto muito por você.
contactmatt
5
@ contactactmatt: Eu não vou desapontá-lo desse sentimento.
B. Clay Shannon
9
Também quero salientar que csv pode ser citado ... Então, usando string.Split não é uma opção viável.
Alxandr
5
Estou recebendo: 'System.Array' não contém uma definição para 'Split' e não foi encontrado nenhum método de extensão 'Split' que aceite um primeiro argumento do tipo 'System.Array' (está faltando uma diretiva de uso ou uma referência de montagem ?)
Kala J
36

Você não pode criar uma matriz imediatamente porque precisa saber o número de linhas desde o início (e isso exigiria a leitura do arquivo csv duas vezes)

Você pode armazenar valores em dois List<T>e depois usá-los ou converter em uma matriz usandoList<T>.ToArray()

Exemplo muito simples:

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

Observe que este é apenas um exemplo muito simples . O uso string.Splitnão leva em consideração os casos em que alguns registros contêm o separador ;dentro dele.
Para uma abordagem mais segura, considere usar algumas bibliotecas específicas de csv como CsvHelper no nuget.

digEmAll
fonte
Não conta por ;fazer parte do valor, por exemplo "value with ; inside it". Valores surround CSV contendo caracteres especiais com aspas duplas para dizer que é uma sequência literal.
ChickenFeet 12/12
1
@ChickenFeet: claro, esse é o motivo da legenda: "Exemplo muito simples" . De qualquer forma, posso adicionar uma observação sobre isso;)
digEmAll
Não se preocupe, eu notei um monte de outras respostas aqui também não conta para ele :)
ChickenFeet
1
Regex.Split (sr.ReadLine (), ", (? = (?: [^ \"] * \ "[^ \"] * \ ") * [^ \"] * $) "); // Encontrado isso em SO ... mais rápido do que uma biblioteca.
Aperte
34

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

Muito intuitivo e fácil de usar. Também possui um pacote nuget que é rápido de implementar: http://nuget.org/packages/CsvHelper/1.17.0 . Também parece ser mantido ativamente do que eu gosto.

É fácil configurá-lo para usar um ponto-e-vírgula: https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations

joshb
fonte
3
Esta é a melhor resposta! Biblioteca robusta e fácil de usar.
Tyler Forsythe
3
A biblioteca CsvHelper é fantástica. Super rápido e fácil de usar.
Paróquia Steve
3
Se você estiver procurando por uma biblioteca que possa lidar com todos os aspectos do formato csv, incluindo cadeias de caracteres entre aspas, use esta. Impressionante!
Matt
Thx, biblioteca muito boa, fácil de usar e muito robusta.
Sebastián Guerrero
2
Como o desempenho se compara com Microsoft.VisualBasic.FileIO.TextFieldParser(cf. resposta de @ Habeeb)?
bovender 07/11/16
33

Eu costumo usar esse analisador do codeproject , já que há um monte de caracteres escapados e similares que ele manipula para mim.

Paulo
fonte
2
isso é muito bom e rápido. Se você estiver em uma situação de negócios e precisar quebrar, use isso.
gjvdkamp
8
Esse analisador está disponível na galeria Nuget como LumenWorks.Framework.IO, caso você não queira se registrar no CodeProject para fazer o download.
Greg McCoy
30

Aqui está minha variação da resposta mais votada:

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

A csvvariável pode ser usada como no exemplo a seguir:

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
fonte
Como você acessa as linhas e colunas na variável csv?
Matthew Bloqueio
1
como você lida com a vírgula de escape?
Kuangwei Zhang
Não manipula vírgulas nas colunas. Melhor usar a biblioteca robusta CsvHelper como por joshb de resposta
Tim Partridge
11

Se você precisar pular linhas e / ou colunas (de cabeça), poderá usá-lo para criar uma 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

Isso é bastante útil se você precisar moldar os dados antes de processá-los ainda mais (supondo que as duas primeiras linhas consistam no título e a primeira coluna seja um título de linha - que você não precisa ter na matriz porque apenas quer considerar os dados).

NB Você pode facilmente obter as manchetes e a 1ª coluna usando o seguinte 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 exemplo de código assume a seguinte estrutura do seu *.csvarquivo:

Matriz CSV

Nota: Se você precisar pular linhas vazias - o que pode ser útil algumas vezes, você pode fazê-lo inserindo

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

entre a fromea selectdeclaração nos LINQ exemplos de código acima.

Matt
fonte
10

Você pode usar a DLL do Microsoft.VisualBasic.FileIO.TextFieldParser em C # para obter melhor desempenho

Veja abaixo o exemplo de código do artigo acima

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
fonte
9
Não é tão eficiente porque o Split não faz tudo o que o TextFieldParser faz. Por exemplo, pule as linhas de comentário, manipule os campos entre aspas e remova os espaços em branco iniciais / finais. Não é exatamente uma comparação 1: 1.
Robert McKee
5

Oi pessoal, Eu criei uma classe estática para fazer isso. + verificação da coluna + remoção do sinal de cota

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
fonte
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
fonte
Obrigado pela ajuda. Pode ajudar a resolver o meu problema. Na verdade, eu tenho que ler dados do arquivo e depois inserir no banco de dados. No momento da inserção, estou recebendo um erro de restrição de chave primária (como eu já tenho dados no banco de dados). Então, eu preciso programar de modo que com a variável já exista e atualizar os dados.
Rushabh Shah
Presumo o primeiro valor se PK - você precisa obter um registro por ID do banco de dados e, se existir, emitir uma instrução UPDATE, caso contrário, insira um novo registro.
Jakub Konecki 12/03
3

Aqui está um caso especial em que um dos campos de dados possui ponto e vírgula (";") como parte dos dados. Nesse caso, a maioria das respostas acima falhará.

Solução, nesse 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
fonte
2

A biblioteca Angara.Table de código aberto permite carregar CSV em colunas digitadas, para que você possa obter as matrizes das colunas. Cada coluna pode ser indexada por nome ou índice. Consulte http://predictionmachines.github.io/Angara.Table/saveload.html .

A biblioteca segue RFC4180 para CSV; permite inferência de tipo e seqüências de linhas múltiplas.

Exemplo:

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

Você pode ver um tipo de coluna usando o tipo Coluna, por exemplo

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

Como a biblioteca é focada em F #, pode ser necessário adicionar uma referência ao assembly FSharp.Core 4.4; clique em 'Add Reference' no projeto e escolha FSharp.Core 4.4 em "Assemblies" -> "Extensions".

Dmitry Voytsekhovskiy
fonte
2

Passei algumas horas procurando uma biblioteca certa, mas finalmente escrevi meu próprio código :) Você pode ler o arquivo (ou banco de dados) com as ferramentas que deseja e, em seguida, aplicar a seguinte rotina a cada linha:

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

Uso o csvreader.com (componente pago) há anos e nunca tive um problema. É sólido, pequeno e rápido, mas você precisa pagar por isso. Você pode definir o delimitador para o que quiser.

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

Eu sou apenas um aluno trabalhando na tese de mestrado, mas foi assim que resolvi e funcionou bem para mim. Primeiro, você seleciona seu arquivo do diretório (apenas no formato csv) e depois coloca os dados nas 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
fonte
0

Ainda errado. Você precisa compensar "" entre aspas. Aqui está a minha solução estilo csv da 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
fonte
3
Ele não lida com o caso quando há mudanças de linha dentro de valores de coluna;)
Emil
0

Eu tenho uma biblioteca que está fazendo exatamente o que você precisa.

Algum tempo atrás, eu escrevi uma biblioteca simples e rápida o suficiente para trabalhar com arquivos CSV. Você pode encontrá-lo no seguinte link: https://github.com/ukushu/DataExporter

Funciona com CSV, como em um array de 2 dimensões. Exatamente como você precisa.

Como exemplo, no caso de você precisar de todos os valores da 3ª linha, basta escrever:

Csv csv = new Csv();

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

var allValuesOf3rdRow = csv.Rows[2];

ou para ler a segunda célula de

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

Veja isso

using CsvFramework;

using System.Collections.Generic;

namespace 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
fonte