Чтение CSV-файла и сохранение значений в массив

317

Я пытаюсь прочитать *.csvфайл.

*.csv-File состоят из двух колонн , разделенных точкой с запятой ( « ; »).

Я могу прочитать *.csv-файл с помощью StreamReader и разделить каждую строку с помощью Split()функции. Я хочу сохранить каждый столбец в отдельный массив, а затем отобразить его.

Возможно ли это сделать?

Рашабх Шах
источник
2
@Marc: к сожалению, в неанглийских культурах (например, в итальянском), когда вы сохраняете Excel в CSV, он использует в ";"качестве разделителя ... это делает CSV нестандартным imo :(
digEmAll
25
Я всегда читаю CSV как символьно-разделенные значения, поскольку люди называют файлы CSV, даже если они не используют запятую в качестве разделителя. И на практике существует так много диалектов с разными правилами цитирования или экранирования, что вы не можете говорить о стандарте, даже если теоретически существует RFC.
CodesInChaos
1
Имя расширения файла CSV теперь должно измениться на DSV - Файл с разделителями-разделителями
Ambuj
Для всех ответов, которые просто разбивают строку на символ разделителя, это не лучший способ. Есть больше правил для формата CSV, которые это не будет охватывать. Лучше всего использовать сторонний парсер. Больше информации
iliketocode

Ответы:

416

Вы можете сделать это так:

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]);
        }
    }
}
Майкл М.
источник
5
Спасибо за это, я забыл, как разбивать строки в CSV-файле (тупой!), Но ваше решение помогло мне :)
Hallaghan
4
Прошло более 3 лет, и этот вопрос до сих пор кому-то помогает. Мне плохо, что ты не получил согласие на это.
AdamMc331
12
Не обрабатывает значения полей запятыми и т. Д.
Майк
12
Если использовать usingпункт здесь, или по крайней мере , вручную так что это ресурс. Close()readerIDisposible
Ассаф Израиль
30
Это также не будет правильно анализировать CSV, написанный как column1;"Special ; char in string";column3- tools.ietf.org/html/rfc4180
Ole K
173

Мой любимый парсер CSV встроен в библиотеку .NET. Это скрытое сокровище внутри пространства имен Microsoft.VisualBasic. Ниже приведен пример кода:

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

Не забудьте добавить ссылку на Microsoft.VisualBasic

Более подробная информация о парсере приведена здесь: http://codeskaters.blogspot.ae/2015/11/c-easiest-csv-parser-built-in-net.html

Хабиб
источник
6
Мне нравится этот вариант больше всего. Мне не нужно беспокоиться о escape-символах, поскольку этот класс является синтаксическим анализатором CSV, а не чем-то созданным вручную.
Тимоти Гонсалес
22
В случае, если кто-то сталкивается с этим и задается вопросом, вам нужно включить ссылку на Microsoft.VisualBasicсборку фреймворка, поскольку на нее обычно не ссылаются по умолчанию.
Апокрифос
3
Хотелось бы, чтобы я запомнил это из моих дней VB6, сэкономил бы мне много времени за эти годы. Хотя некоторые будут разглагольствовать о VB, у меня нет проблем с добавлением пространства имен dll & в мой код, если он имеет значение. Это имеет много значения.
Уолтер
2
Это решение является homerun. очень надежный парсер из моего опыта.
Гленн Ферри
3
Почему только в VB dll?
Марк Чой
75

LINQ способ:

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

^^ Неправильно - Редактировать Ник

Похоже, что первоначальный ответчик пытался заполнить csvдвухмерный массив - массив, содержащий массивы. Каждый элемент в первом массиве содержит массив, представляющий этот номер строки с каждым элементом во вложенном массиве, содержащем данные для этого конкретного столбца.

var csv = from line in lines
          select (line.Split(',')).ToArray();
в-CII
источник
2
Может быть, я что-то упускаю, но я не уверен, в чем смысл вашей переменной csv - разве вы просто не воссоздаете ту же структуру данных, которая записана в строках?
Бен Хьюз
13
@ClayShannon .NET 1.1? Мне очень жаль тебя.
contactmatt
5
@contactmatt: я не буду разубеждать вас в этом чувстве.
Б. Клэй Шеннон
9
Я также хочу отметить, что csv можно заключать в кавычки ... Так что использование string.Split не является жизнеспособным вариантом.
Alxandr
5
Я получаю: «System.Array» не содержит определения для «Split» и не может быть найден метод расширения «Split», принимающий первый аргумент типа «System.Array» (если вы пропустили директиву using или ссылку на сборку ?)
Kala J
36

Вы не можете сразу создать массив, потому что вам нужно знать количество строк с начала (а для этого потребуется дважды прочитать файл csv)

Вы можете хранить значения в два, List<T>а затем использовать их или преобразовать в массив, используяList<T>.ToArray()

Очень простой пример:

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

Обратите внимание, что это очень простой пример . Использование string.Splitне учитывает случаи, когда некоторые записи содержат разделитель ;внутри него.
Для более безопасного подхода рассмотрите возможность использования некоторых специфичных для csv библиотек, таких как CsvHelper, в nuget.

digEmAll
источник
Не учитывает, ;что является частью значения, например "value with ; inside it". CSV окружают значения, содержащие специальные символы с двойными кавычками, чтобы сказать, что это буквальная строка.
ChickenFeet
1
@ChickenFeet: конечно, вот причина подписи: «Очень простой пример» . Во всяком случае, я могу добавить примечание об этом;)
digEmAll
Не беспокойтесь, я заметил много других ответов, здесь также не учитывают это :)
ChickenFeet
1
Regex.Split (sr.ReadLine (), ", (? = (?: [^ \"] * \ "[^ \"] * \ ") * [^ \"] * $) "); // Найдено это на ТАК ... быстрее, чем в библиотеке.
Pinch
34

Просто наткнулся на эту библиотеку: https://github.com/JoshClose/CsvHelper

Очень интуитивно понятный и простой в использовании. Имеет пакет nuget, который быстро реализуется: http://nuget.org/packages/CsvHelper/1.17.0 . Также, кажется, активно поддерживается, что мне нравится.

Настроить его для использования точки с запятой легко: https://github.com/JoshClose/CsvHelper/wiki/Custom-Configurations

joshb
источник
3
Это лучший ответ! Надежная библиотека, с которой легко заходить и кататься.
Тайлер Форсайт
3
Библиотека CsvHelper просто фантастическая. Супер быстрый и простой в использовании.
Стив Пэриш
3
Если вы ищете библиотеку, которая может работать со всеми аспектами формата csv, включая строки в кавычках, используйте эту. Потрясающие!
Мэтт
Спасибо, действительно хорошая библиотека, простая в использовании и очень надежная.
Себастьян Герреро
2
Как соотносится производительность Microsoft.VisualBasic.FileIO.TextFieldParser(см. Ответ Хабиба)?
Bovender
33

Я обычно использую этот синтаксический анализатор из codeproject , так как есть множество экранированных символов и аналогичных, которые он обрабатывает для меня.

Павел
источник
2
эта вещь очень хорошая и быстрая. Если вы находитесь в деловой ситуации и вам нужно взломать, используйте это.
gjvdkamp
8
Этот анализатор доступен в галерее Nuget как LumenWorks.Framework.IO, если вы не хотите регистрироваться для CodeProject, чтобы загрузить его.
Грег Маккой
30

Вот мой вариант ответа с наибольшим количеством голосов:

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

Затем csvпеременную можно использовать как в следующем примере:

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
источник
Как получить доступ к строкам и столбцам в переменной csv?
Мэтью Лок
1
как вы справляетесь с escape-запятой?
Kuangwei Чжан
Не обрабатывает запятые в столбцах. Лучше использовать надежные библиотеки CsvHelper как на joshb - х ответ
Тим Партридж
11

Если вам нужно пропустить (head-) строки и / или столбцы, вы можете использовать это для создания двумерного массива:

    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

Это очень полезно, если вам необходимо сформировать данные перед дальнейшей обработкой (при условии, что первые 2 строки состоят из заголовка, а первый столбец - заголовок строки, который вам не нужен в массиве, потому что вы просто хочу рассмотреть данные).

NB. Вы можете легко получить заголовки и первый столбец, используя следующий код:

    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

Этот пример кода предполагает следующую структуру вашего *.csvфайла:

CSV Matrix

Примечание: если вам нужно пропустить пустые строки - что иногда удобно, вы можете сделать это, вставив

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

между fromи в selectзаявлении в LINQ примеры кода выше.

Matt
источник
10

Вы можете использовать Microsoft.VisualBasic.FileIO.TextFieldParser dll в C # для повышения производительности

получить пример кода из статьи выше

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
источник
9
Это не так эффективно, потому что Split не делает всего, что делает TextFieldParser. Например, пропустите строки комментариев, обработайте поля в кавычках и удалите начальные / конечные пробелы. Не совсем сравнение 1: 1.
Роберт Макки
5

Привет всем, я создал статический класс для этого. + проверка столбца + удаление знака квоты

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

}
Матиас Шмидт
источник
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();
Якуб Конецки
источник
Спасибо за вашу помощь. Это может помочь решить мою проблему. На самом деле я должен прочитать данные из файла, а затем вставить в базу данных. Во время вставки я получаю ошибку ограничения первичного ключа (так как у меня уже есть данные в базе данных). Итак, мне нужно запрограммировать так, чтобы переменная уже существовала, а затем обновить данные.
Рашабх Шах
Я предполагаю первое значение, если PK - вам нужно получить запись по идентификатору из базы данных, и если она существует, чем выполнить инструкцию UPDATE, в противном случае вставьте новую запись.
Якуб Конецки
3

Вот особый случай, когда одно из полей данных имеет точку с запятой (";") как часть своих данных, в этом случае большинство ответов выше потерпит неудачу.

Решение в этом случае будет

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
источник
2

Библиотека Angara.Table с открытым исходным кодом позволяет загружать CSV в типизированные столбцы, поэтому вы можете получить массивы из столбцов. Каждый столбец может быть проиндексирован как по имени, так и по индексу. См. Http://predictionmachines.github.io/Angara.Table/saveload.html .

Библиотека следует RFC4180 для CSV; это позволяет вывод типа и многострочные строки.

Пример:

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

Вы можете увидеть тип столбца, используя тип столбца, например,

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

Поскольку библиотека ориентирована на F #, вам может понадобиться добавить ссылку на сборку FSharp.Core 4.4; нажмите «Добавить ссылку» в проекте и выберите FSharp.Core 4.4 в разделе «Сборки» -> «Расширения».

Дмитрий Войцеховский
источник
2

Я потратил несколько часов в поисках подходящей библиотеки, но, наконец, я написал свой собственный код :) Вы можете читать файлы (или базы данных) любыми инструментами, которые вам нужны, а затем применять следующую процедуру к каждой строке:

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();
}
Збышек Свирски
источник
1

Я использую csvreader.com (платный компонент) в течение многих лет, и у меня никогда не было проблем. Он прочный, маленький и быстрый, но за него нужно платить. Вы можете установить разделитель на то, что вам нравится.

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] ...
}
Оливер Бок
источник
1

Я просто студент, работающий над магистерской диссертацией, но я так решил, и это хорошо сработало для меня. Сначала вы выбираете файл из каталога (только в формате csv), а затем помещаете данные в списки.

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
        );
    }
}
Даниил
источник
0

Все еще не так. Вам нужно компенсировать "" в кавычках. Вот мое решение Microsoft в стиле 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;
    }
}
Р Кин
источник
3
Это не обрабатывает случай, когда есть новые строки внутри значений столбцов;)
Эмиль
0

У меня есть библиотека, которая делает именно то, что вам нужно.

Некоторое время назад я написал простую и достаточно быструю библиотеку для работы с CSV-файлами. Вы можете найти его по следующей ссылке: https://github.com/ukushu/DataExporter

Он работает с CSV как с 2-х мерным массивом. Точно так же, как вам нужно.

Например, в случае, если вам нужны все значения 3-й строки, вам нужно написать:

Csv csv = new Csv();

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

var allValuesOf3rdRow = csv.Rows[2];

или прочитать 2-ю ячейку

var value = csv.Rows[2][1];
Андрей
источник
-1

посмотри на это

использование CsvFramework;

using System.Collections.Generic;

пространство имен 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>();


    }
}

}

Тобиас
источник