Чтение CSV-файла и сохранение значений в массив - PullRequest
275 голосов
/ 12 марта 2011

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

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

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

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

Ответы [ 18 ]

341 голосов
/ 12 марта 2011

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

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]);
        }
    }
}
135 голосов
/ 19 ноября 2015

Мой любимый парсер 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

72 голосов
/ 12 марта 2011

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();
33 голосов
/ 12 марта 2011

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

30 голосов
/ 02 июля 2013

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

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];
}
29 голосов
/ 24 апреля 2013

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

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

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

28 голосов
/ 12 марта 2011

Вы не можете сразу создать массив, потому что вам нужно знать количество строк с начала (а для этого потребуется дважды прочитать файл 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);

нотабене

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

11 голосов
/ 10 марта 2014

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

    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 Вы можете легко получить заголовки и 1-й столбец, используя следующий код:

    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 .

9 голосов
/ 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 голосов
/ 08 ноября 2017

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

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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...