Учитывая, что он был создан годом ранее, чем 1103495, я думаю, что этот вопрос является дубликатом этого.
MattH
2
Спасибо, Мэтт. Я просто пытался связать их вместе, а не указывать, какой из них пришел первым. Вы увидите, что у меня точно такой же текст по другому вопросу, указывающий на этот. Есть ли лучший способ связать два вопроса вместе?
TextFieldParser от Microsoft является стабильным и соответствует RFC 4180 для файлов CSV. Не Microsoft.VisualBasicпугайтесь пространства имен; это стандартный компонент .NET Framework, просто добавьте ссылку на глобальную Microsoft.VisualBasicсборку.
Если вы компилируете для Windows (в отличие от Mono) и не ожидаете, что вам придется анализировать «сломанные» (не соответствующие RFC) файлы CSV, то это будет очевидным выбором, поскольку он бесплатный, неограниченный, стабильный, и активно поддерживается, чего нельзя сказать о FileHelpers.
На самом деле в этом классе нет ничего специфичного для VB, кроме его неудачно названного пространства имен. Я бы определенно выбрал эту библиотеку, если бы мне был нужен только «простой» парсер CSV, потому что не о чем вообще скачивать, распространять или беспокоиться. С этой целью я отредактировал формулировку этого ответа, ориентированную на VB.
Aaronaught
@Aaronaught Я думаю, что ваши правки в основном улучшают ситуацию. Хотя этот RFC не обязательно является официальным, так как многие авторы CSV не соблюдают его, например, Excel не всегда использует запятую в файлах CSV. Кроме того, в моем предыдущем ответе уже не говорилось, что класс можно использовать с C #?
MarkJ
Также TextFieldParserбудет работать с разделителями-табуляторами и прочей странной ерундой, созданной в Excel. Я понимаю, что ваш предыдущий ответ не утверждал, что библиотека была специфичной для VB, мне просто показалось, что она действительно предназначена для VB, а не предназначена для использования с C #, что я не думаю Дело в том, что в MSVB есть несколько действительно полезных классов.
Для этого требуется доступ к файловой системе. Насколько я знаю, нет способа заставить OLEDB работать с потоками в памяти :(
UserControl
3
@UserControl, конечно, требует доступа к файловой системе. Он спросил об импорте файла CSV
Кевин
1
Я не жалуюсь. На самом деле, я бы предпочел решение OLEDB остальным, но я очень много раз разочаровывался, когда мне нужно было проанализировать CSV в приложениях ASP.NET, поэтому я хотел это отметить.
UserControl
12
Если вы ожидаете довольно сложных сценариев парсинга CSV, даже не думайте о развертывании нашего собственного парсера . Есть много отличных инструментов, таких как FileHelpers или даже от CodeProject .
Дело в том, что это довольно распространенная проблема, и вы можете поспорить, что многие разработчики программного обеспечения уже подумали и решили эту проблему.
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - Из
отзыва
Спасибо @techspider. Надеюсь, вы заметили, что этот пост был из периода бета-тестирования StackOverflow: D При этом, как говорят, в настоящее время инструменты CSV лучше получать из пакетов Nuget, поэтому я не уверен, что даже ответы на ссылки защищены от 8-летнего -старые циклы эволюции технологий
Джон Лимджап
9
Брайан дает хорошее решение для преобразования его в строго типизированную коллекцию.
Большинство приведенных методов синтаксического анализа CSV не учитывают экранирование полей или некоторые другие тонкости файлов CSV (например, обрезку полей). Вот код, который я использую лично. Он немного грубоват и практически не содержит сообщений об ошибках.
publicstaticIList<IList<string>>Parse(string content){IList<IList<string>> records =newList<IList<string>>();StringReader stringReader =newStringReader(content);bool inQoutedString =false;IList<string> record =newList<string>();StringBuilder fieldBuilder =newStringBuilder();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 =newStringBuilder();
records.Add(record);
record =newList<string>();
inQoutedString =false;}}elseif(fieldBuilder.Length==0&&!inQoutedString){if(char.IsWhiteSpace(readChar)){// Ignore leading whitespace}elseif(readChar =='"'){
inQoutedString =true;}elseif(readChar ==','){
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();}else{
fieldBuilder.Append(readChar);}}elseif(readChar ==','){if(inQoutedString){
fieldBuilder.Append(',');}else{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();}}elseif(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;}
Обратите внимание, что это не обрабатывает крайний случай, когда поля не разделяются двойными кавычками, но имеют внутри заключенную в кавычки строку. См. Этот пост для лучшего расширения, а также некоторых ссылок на некоторые соответствующие библиотеки.
Я согласен с @ NotMyself . FileHelpers хорошо протестирован и обрабатывает все виды крайних случаев, с которыми вам в конечном итоге придется иметь дело, если вы сделаете это самостоятельно. Взгляните на то, что делает FileHelpers, и пишите свое только в том случае, если вы абсолютно уверены, что либо (1) вам никогда не понадобится обрабатывать крайние случаи, которые делает FileHelpers, либо (2) вы любите писать такие вещи и собираетесь будьте вне себя от радости, когда вам придется разбирать такие вещи:
Мне было скучно, поэтому я изменил кое-что, что написал. Он пытается инкапсулировать синтаксический анализ в объектно-ориентированном стиле, сокращая количество итераций через файл, он повторяется только один раз в верхней части foreach.
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.IO;namespaceConsoleApplication1{classProgram{staticvoidMain(string[] args){// usage:// note this wont run as getting streams is not Implemented// but will get you startedCSVFileParser fileParser =newCSVFileParser();// TO Do: configure fileparserPersonParser personParser =newPersonParser(fileParser);List<Person> persons =newList<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 desireforeach(Person person in personParser.GetPersons()){
persons.Add(person);}// now we have a list of Person objects}}publicabstractclassCSVParser{protectedString[] deliniators ={","};protectedinternalIEnumerable<String[]>GetRecords(){Stream stream =GetStream();StreamReader reader =newStreamReader(stream);String[] aRecord;while(!reader.EndOfStream){
aRecord = reader.ReadLine().Split(deliniators,StringSplitOptions.None);yieldreturn aRecord;}}protectedabstractStreamGetStream();}publicclassCSVFileParser:CSVParser{// to do: add logic to get a stream from a fileprotectedoverrideStreamGetStream(){thrownewNotImplementedException();}}publicclassCSVWebParser:CSVParser{// to do: add logic to get a stream from a web requestprotectedoverrideStreamGetStream(){thrownewNotImplementedException();}}publicclassPerson{publicStringName{get;set;}publicStringAddress{get;set;}publicDateTime DOB {get;set;}}publicclassPersonParser{publicPersonParser(CSVParser parser){this.Parser= parser;}publicCSVParserParser{get;set;}publicIEnumerable<Person>GetPersons(){foreach(String[] record inthis.Parser.GetRecords()){yieldreturnnewPerson(){Name= record[0],Address= record[1],
DOB =DateTime.Parse(record[2]),};}}}}
Хороший простой способ сделать это - открыть файл и прочитать каждую строку в массив, связанный список, структуру данных по вашему выбору. Однако будьте осторожны при работе с первой строкой.
Возможно, это над вашей головой, но, похоже, есть прямой способ получить к ним доступ с помощью строки подключения .
Почему бы не попробовать использовать Python вместо C # или VB? В нем есть хороший модуль CSV для импорта, который сделает всю тяжелую работу за вас.
Не переходите на Python с VB ради парсера CSV. Один в VB. Хотя, как ни странно, в ответах на этот вопрос его, кажется, проигнорировали. msdn.microsoft.com/en-us/library/…
MarkJ 02
1
Этим летом мне пришлось использовать парсер CSV в .NET для проекта, и я остановился на драйвере Microsoft Jet Text. Вы указываете папку с помощью строки подключения, а затем запрашиваете файл с помощью оператора SQL Select. Вы можете указать строгие типы с помощью файла schema.ini. Сначала я этого не делал, но потом я получал плохие результаты, когда тип данных не сразу определялся, например номера IP или запись типа «XYQ 3.9 SP1».
Я столкнулся с одним ограничением: он не может обрабатывать имена столбцов длиной более 64 символов; он усекает. Это не должно быть проблемой, за исключением того, что я имел дело с очень плохо спроектированными входными данными. Он возвращает набор данных ADO.NET.
Это было лучшее решение, которое я нашел. Я бы опасался развертывать свой собственный анализатор CSV, поскольку я, вероятно, пропустил бы некоторые из конечных случаев, и я не нашел там других бесплатных пакетов синтаксического анализа CSV для .NET.
РЕДАКТИРОВАТЬ: Кроме того, в каталоге может быть только один файл schema.ini, поэтому я динамически добавлял к нему, чтобы строго ввести необходимые столбцы. Он будет строго печатать только указанные столбцы и делать выводы для любого неуказанного поля. Мне это очень понравилось, так как я имел дело с импортом жидкого CSV с более чем 70 столбцами и не хотел указывать каждый столбец, а только некорректно работающие.
Могут быть библиотеки, которыми вы могли бы помочь, но это, вероятно, настолько просто, насколько это возможно. Просто убедитесь, что у вас не может быть запятых в данных, иначе вам нужно будет лучше проанализировать их.
Ответы:
TextFieldParser от Microsoft является стабильным и соответствует RFC 4180 для файлов CSV. Не
Microsoft.VisualBasic
пугайтесь пространства имен; это стандартный компонент .NET Framework, просто добавьте ссылку на глобальнуюMicrosoft.VisualBasic
сборку.Если вы компилируете для Windows (в отличие от Mono) и не ожидаете, что вам придется анализировать «сломанные» (не соответствующие RFC) файлы CSV, то это будет очевидным выбором, поскольку он бесплатный, неограниченный, стабильный, и активно поддерживается, чего нельзя сказать о FileHelpers.
См. Также: Как читать из текстовых файлов с разделителями-запятыми в Visual Basic для примера кода VB.
источник
TextFieldParser
будет работать с разделителями-табуляторами и прочей странной ерундой, созданной в Excel. Я понимаю, что ваш предыдущий ответ не утверждал, что библиотека была специфичной для VB, мне просто показалось, что она действительно предназначена для VB, а не предназначена для использования с C #, что я не думаю Дело в том, что в MSVB есть несколько действительно полезных классов.Используйте соединение OleDB.
источник
Если вы ожидаете довольно сложных сценариев парсинга CSV, даже не думайте о развертывании нашего собственного парсера . Есть много отличных инструментов, таких как FileHelpers или даже от CodeProject .
Дело в том, что это довольно распространенная проблема, и вы можете поспорить, что многие разработчики программного обеспечения уже подумали и решили эту проблему.
источник
Брайан дает хорошее решение для преобразования его в строго типизированную коллекцию.
Большинство приведенных методов синтаксического анализа CSV не учитывают экранирование полей или некоторые другие тонкости файлов CSV (например, обрезку полей). Вот код, который я использую лично. Он немного грубоват и практически не содержит сообщений об ошибках.
Обратите внимание, что это не обрабатывает крайний случай, когда поля не разделяются двойными кавычками, но имеют внутри заключенную в кавычки строку. См. Этот пост для лучшего расширения, а также некоторых ссылок на некоторые соответствующие библиотеки.
источник
Я согласен с @ NotMyself . FileHelpers хорошо протестирован и обрабатывает все виды крайних случаев, с которыми вам в конечном итоге придется иметь дело, если вы сделаете это самостоятельно. Взгляните на то, что делает FileHelpers, и пишите свое только в том случае, если вы абсолютно уверены, что либо (1) вам никогда не понадобится обрабатывать крайние случаи, которые делает FileHelpers, либо (2) вы любите писать такие вещи и собираетесь будьте вне себя от радости, когда вам придется разбирать такие вещи:
1, «Билл», «Смит», «Супервайзер», «Без комментариев»
2, «Дрейк», «О'Мэлли», «Дворник»,
Ой, меня не цитируют и я на новой строчке!
источник
Мне было скучно, поэтому я изменил кое-что, что написал. Он пытается инкапсулировать синтаксический анализ в объектно-ориентированном стиле, сокращая количество итераций через файл, он повторяется только один раз в верхней части foreach.
источник
На CodeProject есть две статьи, которые предоставляют код для решения: одна использует StreamReader, а другая импортирует данные CSV с помощью текстового драйвера Microsoft .
источник
Хороший простой способ сделать это - открыть файл и прочитать каждую строку в массив, связанный список, структуру данных по вашему выбору. Однако будьте осторожны при работе с первой строкой.
Возможно, это над вашей головой, но, похоже, есть прямой способ получить к ним доступ с помощью строки подключения .
Почему бы не попробовать использовать Python вместо C # или VB? В нем есть хороший модуль CSV для импорта, который сделает всю тяжелую работу за вас.
источник
Этим летом мне пришлось использовать парсер CSV в .NET для проекта, и я остановился на драйвере Microsoft Jet Text. Вы указываете папку с помощью строки подключения, а затем запрашиваете файл с помощью оператора SQL Select. Вы можете указать строгие типы с помощью файла schema.ini. Сначала я этого не делал, но потом я получал плохие результаты, когда тип данных не сразу определялся, например номера IP или запись типа «XYQ 3.9 SP1».
Я столкнулся с одним ограничением: он не может обрабатывать имена столбцов длиной более 64 символов; он усекает. Это не должно быть проблемой, за исключением того, что я имел дело с очень плохо спроектированными входными данными. Он возвращает набор данных ADO.NET.
Это было лучшее решение, которое я нашел. Я бы опасался развертывать свой собственный анализатор CSV, поскольку я, вероятно, пропустил бы некоторые из конечных случаев, и я не нашел там других бесплатных пакетов синтаксического анализа CSV для .NET.
РЕДАКТИРОВАТЬ: Кроме того, в каталоге может быть только один файл schema.ini, поэтому я динамически добавлял к нему, чтобы строго ввести необходимые столбцы. Он будет строго печатать только указанные столбцы и делать выводы для любого неуказанного поля. Мне это очень понравилось, так как я имел дело с импортом жидкого CSV с более чем 70 столбцами и не хотел указывать каждый столбец, а только некорректно работающие.
источник
Я ввел код. Результат в средстве просмотра данных выглядел хорошо. Он анализирует одну строку текста в массив объектов.
источник
Если вы можете гарантировать, что в данных нет запятых, то, вероятно, самым простым способом будет использование String.split .
Например:
Могут быть библиотеки, которыми вы могли бы помочь, но это, вероятно, настолько просто, насколько это возможно. Просто убедитесь, что у вас не может быть запятых в данных, иначе вам нужно будет лучше проанализировать их.
источник