/* * License: CPOL * Source: https://www.codeproject.com/Tips/823670/Csharp-Light-and-Fast-CSV-Parser * Author: Yuriy Magurdumov */ using System; using System.Collections.Generic; using System.Text; namespace HeuristicLab.BenchmarkSuite { using System.IO; public static class CsvParser { private static Tuple> HeadAndTail(this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); var en = source.GetEnumerator(); en.MoveNext(); return Tuple.Create(en.Current, EnumerateTail(en)); } private static IEnumerable EnumerateTail(IEnumerator en) { while (en.MoveNext()) yield return en.Current; } public static IEnumerable> Parse(string content, char delimiter, char qualifier) { using (var reader = new StringReader(content)) return Parse(reader, delimiter, qualifier); } public static Tuple, IEnumerable>> ParseHeadAndTail(TextReader reader, char delimiter, char qualifier) { return HeadAndTail(Parse(reader, delimiter, qualifier)); } public static IEnumerable> Parse(TextReader reader, char delimiter, char qualifier) { var inQuote = false; var record = new List(); var sb = new StringBuilder(); while (reader.Peek() != -1) { var readChar = (char)reader.Read(); if (readChar == '\n' || (readChar == '\r' && (char)reader.Peek() == '\n')) { // If it's a \r\n combo consume the \n part and throw it away. if (readChar == '\r') reader.Read(); if (inQuote) { if (readChar == '\r') sb.Append('\r'); sb.Append('\n'); } else { if (record.Count > 0 || sb.Length > 0) { record.Add(sb.ToString()); sb.Clear(); } if (record.Count > 0) yield return record; record = new List(record.Count); } } else if (sb.Length == 0 && !inQuote) { if (readChar == qualifier) inQuote = true; else if (readChar == delimiter) { record.Add(sb.ToString()); sb.Clear(); //} else if (char.IsWhiteSpace(readChar)) { // Ignore leading whitespace } else sb.Append(readChar); } else if (readChar == delimiter) { if (inQuote) sb.Append(delimiter); else { record.Add(sb.ToString()); sb.Clear(); } } else if (readChar == qualifier) { if (inQuote) { if ((char)reader.Peek() == qualifier) { reader.Read(); sb.Append(qualifier); } else inQuote = false; } else sb.Append(readChar); } else sb.Append(readChar); } if (record.Count > 0 || sb.Length > 0) record.Add(sb.ToString()); if (record.Count > 0) yield return record; } } }