CSV Импорт файла в .Net

голоса
99

Я понимаю, что это вопрос новичка, но я ищу простое решение - кажется, что там должен быть один.

Какой самый лучший способ, чтобы импортировать файл CSV в сильно типизированных структуры данных? Опять простой = лучше.

Задан 05/08/2008 в 05:43
источник пользователем
На других языках...                            


12 ответов

голоса
72

Microsoft, TextFieldParser является стабильным и следует RFC 4180 для CSV - файлов. Не пугайтесь Microsoft.VisualBasicименами; это стандартный компонент в .NET Framework, просто добавьте ссылку на глобальную Microsoft.VisualBasicсборку.

Если вы собираете для Windows, (в отличие от Mono) и не ожидаем того, чтобы разобрать «Broken» (не-RFC-совместимый) CSV файлы, то это будет очевидным выбором, поскольку это бесплатно, без ограничений, стабильной, и активно поддерживается, большинство из которых не может быть сказано для FileHelpers.

Смотрите также: Как Чтение из запятых текстовых файлов в Visual Basic для примера VB кода.

Ответил 01/04/2009 d 20:58
источник пользователем

голоса
48

Проверьте FileHelpers Open Source Library .

Ответил 05/08/2008 d 05:47
источник пользователем

голоса
21

Используйте соединение OleDB.

String sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\InputDirectory\\;Extended Properties='text;HDR=Yes;FMT=Delimited'";
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
DataTable dt = new DataTable();
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM file.csv", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
objAdapter1.Fill(dt);
objConn.Close();
Ответил 05/11/2008 d 15:41
источник пользователем

голоса
12

Если вы ожидаете , довольно сложные сценарии для CSV разбора, даже не придумаешь свертывать наш собственный парсер . Есть много прекрасных инструментов там, как FileHelpers , или даже те из CodeProject .

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

Ответил 17/08/2008 d 00:44
источник пользователем

голоса
9

Я согласен с @ NotMyself . FileHelpers хорошо протестирована и обрабатывает все виды крайние случаи , что вы будете в конечном итоге придется иметь дело с тем, если вы сделаете это сами. Посмотрите на то , что FileHelpers делает и только написать свой собственный , если вы абсолютно уверены в том , что либо (1) вы никогда не должны обращаться с крайними случаями FileHelpers делает, или (2) вы любите писать такого рода вещи и собираются быть вне себя от радости , когда вы должны разобрать вещи , как это:

1, "Билл", "Смит", "руководитель", "No Comment"

2, 'Дрейк', 'О'Мэлли', "Дворник,

К сожалению, я не цитировал, и я на новой линии!

Ответил 17/08/2008 d 00:53
источник пользователем

голоса
9

Брайан дает хорошее решение для преобразования его в строго типизированных коллекции.

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

public static IList<IList<string>> Parse(string content)
{
    IList<IList<string>> records = new List<IList<string>>();

    StringReader stringReader = new StringReader(content);

    bool inQoutedString = false;
    IList<string> record = new List<string>();
    StringBuilder fieldBuilder = new StringBuilder();
    while (stringReader.Peek() != -1)
    {
        char readChar = (char)stringReader.Read();

        if (readChar == '\n' || (readChar == '\r' && stringReader.Peek() == '\n'))
        {
            // If it's a \r\n combo consume the \n part and throw it away.
            if (readChar == '\r')
            {
                stringReader.Read();
            }

            if (inQoutedString)
            {
                if (readChar == '\r')
                {
                    fieldBuilder.Append('\r');
                }
                fieldBuilder.Append('\n');
            }
            else
            {
                record.Add(fieldBuilder.ToString().TrimEnd());
                fieldBuilder = new StringBuilder();

                records.Add(record);
                record = new List<string>();

                inQoutedString = false;
            }
        }
        else if (fieldBuilder.Length == 0 && !inQoutedString)
        {
            if (char.IsWhiteSpace(readChar))
            {
                // Ignore leading whitespace
            }
            else if (readChar == '"')
            {
                inQoutedString = true;
            }
            else if (readChar == ',')
            {
                record.Add(fieldBuilder.ToString().TrimEnd());
                fieldBuilder = new StringBuilder();
            }
            else
            {
                fieldBuilder.Append(readChar);
            }
        }
        else if (readChar == ',')
        {
            if (inQoutedString)
            {
                fieldBuilder.Append(',');
            }
            else
            {
                record.Add(fieldBuilder.ToString().TrimEnd());
                fieldBuilder = new StringBuilder();
            }
        }
        else if (readChar == '"')
        {
            if (inQoutedString)
            {
                if (stringReader.Peek() == '"')
                {
                    stringReader.Read();
                    fieldBuilder.Append('"');
                }
                else
                {
                    inQoutedString = false;
                }
            }
            else
            {
                fieldBuilder.Append(readChar);
            }
        }
        else
        {
            fieldBuilder.Append(readChar);
        }
    }
    record.Add(fieldBuilder.ToString().TrimEnd());
    records.Add(record);

    return records;
}

Обратите внимание , что это не обрабатывает края случай полей не deliminated в двойных кавычках, но meerley имея строку в кавычках внутри него. Смотрите этот пост для немногих лучшего expanation, а также некоторые ссылки на некоторые собственные библиотеки.

Ответил 08/08/2008 d 17:20
источник пользователем

голоса
6

Мне было скучно, поэтому я модифицирована некоторые вещи я написал. Это попробовать, чтобы инкапсулировать разбор в ОО манере whle вырубки от количества итераций файла, это только итерация один раз в верхнем Еогеаспе.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {

            // usage:

            // note this wont run as getting streams is not Implemented

            // but will get you started

            CSVFileParser fileParser = new CSVFileParser();

            // TO Do:  configure fileparser

            PersonParser personParser = new PersonParser(fileParser);

            List<Person> persons = new List<Person>();
            // if the file is large and there is a good way to limit
            // without having to reparse the whole file you can use a 
            // linq query if you desire
            foreach (Person person in personParser.GetPersons())
            {
                persons.Add(person);
            }

            // now we have a list of Person objects
        }
    }

    public abstract  class CSVParser 
    {

        protected String[] deliniators = { "," };

        protected internal IEnumerable<String[]> GetRecords()
        {

            Stream stream = GetStream();
            StreamReader reader = new StreamReader(stream);

            String[] aRecord;
            while (!reader.EndOfStream)
            {
                  aRecord = reader.ReadLine().Split(deliniators,
                   StringSplitOptions.None);

                yield return aRecord;
            }

        }

        protected abstract Stream GetStream(); 

    }

    public class CSVFileParser : CSVParser
    {
        // to do: add logic to get a stream from a file

        protected override Stream GetStream()
        {
            throw new NotImplementedException();
        } 
    }

    public class CSVWebParser : CSVParser
    {
        // to do: add logic to get a stream from a web request

        protected override Stream GetStream()
        {
            throw new NotImplementedException();
        }
    }

    public class Person
    {
        public String Name { get; set; }
        public String Address { get; set; }
        public DateTime DOB { get; set; }
    }

    public class PersonParser 
    {

        public PersonParser(CSVParser parser)
        {
            this.Parser = parser;
        }

        public CSVParser Parser { get; set; }

        public  IEnumerable<Person> GetPersons()
        {
            foreach (String[] record in this.Parser.GetRecords())
            {
                yield return new Person()
                {
                    Name = record[0],
                    Address = record[1],
                    DOB = DateTime.Parse(record[2]),
                };
            }
        }
    }
}
Ответил 08/08/2008 d 10:39
источник пользователем

голоса
5

Есть две статьи о CodeProject , которые предоставляют код для решения, тот , который использует StreamReader и тот , который импортирует данные CSV с помощью текстового драйвера Microsoft .

Ответил 05/08/2008 d 06:24
источник пользователем

голоса
2

Хороший простой способ сделать это, чтобы открыть файл и читать каждую строку в массив, связанный список, структура данных-оф-ваш-выбор. Будьте осторожны при обращении с первой линии, хотя.

Это может быть над головой, но там , кажется, прямой путь доступа к ним , а также с помощью строки подключения .

Почему бы не попробовать использовать Python вместо C # или VB? Она имеет хороший модуль CSV для импорта, который делает всю тяжелую работу за вас.

Ответил 05/08/2008 d 05:49
источник пользователем

голоса
1

Я напечатал в некотором коде. В результате в datagridviewer выглядел хорошо. Она анализирует одну строку текста в коллекции объектов.

    enum quotestatus
    {
        none,
        firstquote,
        secondquote
    }
    public static System.Collections.ArrayList Parse(string line,string delimiter)
    {        
        System.Collections.ArrayList ar = new System.Collections.ArrayList();
        StringBuilder field = new StringBuilder();
        quotestatus status = quotestatus.none;
        foreach (char ch in line.ToCharArray())
        {                                
            string chOmsch = "char";
            if (ch == Convert.ToChar(delimiter))
            {
                if (status== quotestatus.firstquote)
                {
                    chOmsch = "char";
                }                         
                else
                {
                    chOmsch = "delimiter";                    
                }                    
            }

            if (ch == Convert.ToChar(34))
            {
                chOmsch = "quotes";           
                if (status == quotestatus.firstquote)
                {
                    status = quotestatus.secondquote;
                }
                if (status == quotestatus.none )
                {
                    status = quotestatus.firstquote;
                }
            }

            switch (chOmsch)
            {
                case "char":
                    field.Append(ch);
                    break;
                case "delimiter":                        
                    ar.Add(field.ToString());
                    field.Clear();
                    break;
                case "quotes":
                    if (status==quotestatus.firstquote)
                    {
                        field.Clear();                            
                    }
                    if (status== quotestatus.secondquote)
                    {                                                                           
                            status =quotestatus.none;                                
                    }                    
                    break;
            }
        }
        if (field.Length != 0)            
        {
            ar.Add(field.ToString());                
        }           
        return ar;
    }
Ответил 09/09/2011 d 11:02
источник пользователем

голоса
1

Я должен был использовать парсер CSV в .NET для проекта этим летом и обосновалась на текст драйвера Microsoft Jet. Вы указываете папку, используя строку подключения, а затем запросить файл с помощью SQL Select заявление. Вы можете указать сильные типы, используя Schema.ini файл. Я не делал это сначала, но потом я получаю плохие результаты, когда тип данных не сразу, например, номера IP или запись типа «XYQ 3.9 SP1».

Одно ограничение я столкнулся в том, что он не может обрабатывать имена столбцов выше 64 символов; он отсекает. Это не должно быть проблемой, за исключением того, что имею дело с очень плохо спроектированных входных данных. Она возвращает набор данных ADO.NET.

Это было лучшим решением, которое я нашел. Я бы с осторожностью относиться к прокатке собственного CSV-анализатору, так как я, вероятно, пропустить некоторые из конечных случаев, и я не нашел какие-либо другие пакеты разбора бесплатно CSV для .NET там.

EDIT: Кроме того, может быть только один Schema.ini файл в каталоге, так что я динамически добавляется к нему сильно введите необходимые столбцы. Он будет только сильно ввести столбцы, указанные и вывод для любого неопределенного поля. Я действительно оценил это, как я имел дело с импортом жидкостью 70+ столбца CSV и не хочу, чтобы указать каждый столбец, только плохие поведение из них.

Ответил 16/08/2008 d 23:15
источник пользователем

голоса
0

Если вы можете гарантировать , что нет запятые в данных, то самый простой способ, вероятно , будет использовать String.split .

Например:

String[] values = myString.Split(',');
myObject.StringField = values[0];
myObject.IntField = Int32.Parse(values[1]);

Там могут быть библиотеки, которые вы могли бы использовать, чтобы помочь, но это, вероятно, так же просто, как вы можете получить. Просто убедитесь, что вы не можете иметь запятые в данных, в противном случае вам нужно будет разобрать его лучше.

Ответил 05/08/2008 d 06:02
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more