Как прочитать файл CSV в .NET Datatable - PullRequest
155 голосов
/ 26 июня 2009

Как я могу загрузить файл CSV в System.Data.DataTable, создавая таблицу данных на основе файла CSV?

Позволяет ли это обычная функциональность ADO.net?

Ответы [ 20 ]

88 голосов
/ 26 июня 2009

Я использовал OleDb провайдера. Однако возникают проблемы, если вы читаете в строках с числовыми значениями, но хотите, чтобы они обрабатывались как текст. Однако вы можете обойти эту проблему, создав файл schema.ini. Вот мой метод, который я использовал:

// using System.Data;
// using System.Data.OleDb;
// using System.Globalization;
// using System.IO;

static DataTable GetDataTableFromCsv(string path, bool isFirstRowHeader)
{
    string header = isFirstRowHeader ? "Yes" : "No";

    string pathOnly = Path.GetDirectoryName(path);
    string fileName = Path.GetFileName(path);

    string sql = @"SELECT * FROM [" + fileName + "]";

    using(OleDbConnection connection = new OleDbConnection(
              @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pathOnly + 
              ";Extended Properties=\"Text;HDR=" + header + "\""))
    using(OleDbCommand command = new OleDbCommand(sql, connection))
    using(OleDbDataAdapter adapter = new OleDbDataAdapter(command))
    {
        DataTable dataTable = new DataTable();
        dataTable.Locale = CultureInfo.CurrentCulture;
        adapter.Fill(dataTable);
        return dataTable;
    }
}
84 голосов
/ 26 июня 2009

Вот отличный класс, который будет копировать данные CSV в таблицу данных, используя структуру данных для создания DataTable:

Портативный и эффективный универсальный синтаксический анализатор для плоских файлов

Он прост в настройке и использовании. Я призываю вас взглянуть.

40 голосов
/ 26 июня 2009

Я решил использовать Себастьен Лорион Csv Reader .

Предложение Джея Риггса также является отличным решением, но мне просто не нужны были все функции, которые предоставляет Generic Parser Эндрю Риссинга .

ОБНОВЛЕНИЕ 10/25/2010

После использования Csv Reader Себастьяна Лориона в моем проекте в течение почти полутора лет я обнаружил, что он генерирует исключения при разборе некоторых CSV-файлов, которые, по моему мнению, хорошо сформированы.

Итак, я переключился на Общий анализатор Эндрю Риссинга , и, похоже, дела идут намного лучше.

ОБНОВЛЕНИЕ 9/22/2014

В наши дни я в основном использую этот метод расширения для чтения текста с разделителями:

https://github.com/Core-Techs/Common/blob/master/CoreTechs.Common/Text/DelimitedTextExtensions.cs#L22

https://www.nuget.org/packages/CoreTechs.Common/

ОБНОВЛЕНИЕ 2/20/2015

Пример: * * тысяча тридцать-один

var csv = @"Name, Age
Ronnie, 30
Mark, 40
Ace, 50";

TextReader reader = new StringReader(csv);
var table = new DataTable();
using(var it = reader.ReadCsvWithHeader().GetEnumerator())
{

    if (!it.MoveNext()) return;

    foreach (var k in it.Current.Keys)
        table.Columns.Add(k);

    do
    {
        var row = table.NewRow();
        foreach (var k in it.Current.Keys)
            row[k] = it.Current[k];

        table.Rows.Add(row);

    } while (it.MoveNext());
}
28 голосов
/ 30 декабря 2014

Эй, он работает 100%

  public static DataTable ConvertCSVtoDataTable(string strFilePath)
  {
    DataTable dt = new DataTable();
    using (StreamReader sr = new StreamReader(strFilePath))
    {
        string[] headers = sr.ReadLine().Split(',');
        foreach (string header in headers)
        {
            dt.Columns.Add(header);
        }
        while (!sr.EndOfStream)
        {
            string[] rows = sr.ReadLine().Split(',');
            DataRow dr = dt.NewRow();
            for (int i = 0; i < headers.Length; i++)
            {
                dr[i] = rows[i];
            }
            dt.Rows.Add(dr);
        }

    }


    return dt;
   }

CSV-изображение enter image description here

Таблица данных импортирована enter image description here

13 голосов
/ 18 августа 2010

Мы всегда использовали драйвер Jet.OLEDB, пока не начали переходить на 64-битные приложения. Microsoft не выпустила и не выпустит 64-битный драйвер Jet. Вот простое решение, которое мы придумали, которое использует File.ReadAllLines и String.Split для чтения и анализа CSV-файла и загрузки DataTable вручную. Как отмечено выше, он НЕ обрабатывает ситуацию, когда одно из значений столбца содержит запятую. Мы используем это главным образом для чтения пользовательских файлов конфигурации - приятная часть использования CSV-файлов заключается в том, что мы можем редактировать их в Excel.

string CSVFilePathName = @"C:\test.csv";
string[] Lines = File.ReadAllLines(CSVFilePathName);
string[] Fields;
Fields = Lines[0].Split(new char[] { ',' });
int Cols = Fields.GetLength(0);
DataTable dt = new DataTable();
//1st row must be column names; force lower case to ensure matching later on.
for (int i = 0; i < Cols; i++)
    dt.Columns.Add(Fields[i].ToLower(), typeof(string));
DataRow Row;
for (int i = 1; i < Lines.GetLength(0); i++)
{
    Fields = Lines[i].Split(new char[] { ',' });
    Row = dt.NewRow();
    for (int f = 0; f < Cols; f++)
        Row[f] = Fields[f];
    dt.Rows.Add(Row);
}
8 голосов
/ 06 февраля 2013

это код, который я использую, но ваши приложения должны работать с чистой версией 3.5

private void txtRead_Click(object sender, EventArgs e)
        {
           // var filename = @"d:\shiptest.txt";

            openFileDialog1.InitialDirectory = "d:\\";
            openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            DialogResult result = openFileDialog1.ShowDialog();
            if (result == DialogResult.OK)
            {
                if (openFileDialog1.FileName != "")
                {
                    var reader = ReadAsLines(openFileDialog1.FileName);

                    var data = new DataTable();

                    //this assume the first record is filled with the column names
                    var headers = reader.First().Split(',');
                    foreach (var header in headers)
                    {
                        data.Columns.Add(header);
                    }

                    var records = reader.Skip(1);
                    foreach (var record in records)
                    {
                        data.Rows.Add(record.Split(','));
                    }

                    dgList.DataSource = data;
                }
            }
        }

        static IEnumerable<string> ReadAsLines(string filename)
        {
            using (StreamReader reader = new StreamReader(filename))
                while (!reader.EndOfStream)
                    yield return reader.ReadLine();
        }
6 голосов
/ 28 августа 2013

Вы можете достичь этого с помощью 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;
        }
4 голосов
/ 02 сентября 2011

Я наткнулся на этот фрагмент кода, который использует Linq и регулярные выражения для анализа файла CSV. Ссылочной статье уже более полутора лет, но она не нашла более точного способа анализа CSV с использованием Linq (и регулярных выражений), чем эта. Предостережение - это регулярное выражение, применяемое здесь для файлов с разделителями-запятыми (будет обнаруживать запятые внутри кавычек!) И то, что оно может не очень хорошо восприниматься в заголовках, но есть способ преодолеть их). Взять пик:

Dim lines As String() = System.IO.File.ReadAllLines(strCustomerFile)
Dim pattern As String = ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
Dim r As System.Text.RegularExpressions.Regex = New System.Text.RegularExpressions.Regex(pattern)
Dim custs = From line In lines _
            Let data = r.Split(line) _
                Select New With {.custnmbr = data(0), _
                                 .custname = data(1)}
For Each cust In custs
    strCUSTNMBR = Replace(cust.custnmbr, Chr(34), "")
    strCUSTNAME = Replace(cust.custname, Chr(34), "")
Next
3 голосов
/ 10 мая 2013

Для тех из вас, кто не хочет использовать внешнюю библиотеку и предпочитает не использовать OleDB, см. Пример ниже. Все, что я нашел, было либо OleDB, внешней библиотекой, либо просто разделением на запятую! В моем случае OleDB не работал, поэтому я хотел что-то другое.

Я нашел статью MarkJ, которая ссылалась на метод Microsoft.VisualBasic.FileIO.TextFieldParser, как показано здесь . Статья написана на VB и не возвращает данных, поэтому смотрите мой пример ниже.

public static DataTable LoadCSV(string path, bool hasHeader)
    {
        DataTable dt = new DataTable();

        using (var MyReader = new Microsoft.VisualBasic.FileIO.TextFieldParser(path))
        {
            MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited;
            MyReader.Delimiters = new String[] { "," };

            string[] currentRow;

            //'Loop through all of the fields in the file.  
            //'If any lines are corrupt, report an error and continue parsing.  
            bool firstRow = true;
            while (!MyReader.EndOfData)
            {
                try
                {
                    currentRow = MyReader.ReadFields();

                    //Add the header columns
                    if (hasHeader && firstRow)
                    {
                        foreach (string c in currentRow)
                        {
                            dt.Columns.Add(c, typeof(string));
                        }

                        firstRow = false;
                        continue;
                    }

                    //Create a new row
                    DataRow dr = dt.NewRow();
                    dt.Rows.Add(dr);

                    //Loop thru the current line and fill the data out
                    for(int c = 0; c < currentRow.Count(); c++)
                    {
                        dr[c] = currentRow[c];
                    }
                }
                catch (Microsoft.VisualBasic.FileIO.MalformedLineException ex)
                {
                    //Handle the exception here
                }
            }
        }

        return dt;
    }
3 голосов
/ 12 февраля 2013

Лучший вариант, который я нашел, и он решает проблемы, когда у вас могут быть установлены разные версии Office, а также 32/64-битные проблемы, такие как Чак Бевитт упомянул , это FileHelpers .

Он может быть добавлен к ссылкам на ваш проект с помощью NuGet и предоставляет однострочное решение:

CommonEngine.CsvToDataTable(path, "ImportRecord", ',', true);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...