/// <summary> /// Parses CSV file. and returns <seealso cref="CsvReader"/> initialized with the content. /// </summary> /// <param name="csvFilePath"> /// The CSV file path. /// </param> /// <param name="hasHeader"> /// Indicates if the file has a header. /// </param> /// <param name="options"> /// The options. /// </param> /// <returns> /// The <seealso cref="CsvReader"/> initialized with the content of the CSV <paramref name="csvFilePath"/>. /// </returns> public static CsvReader Parse(string csvFilePath, bool hasHeader = true, CsvReaderOptions options = null) { var stream = File.OpenRead(csvFilePath); return(new CsvReader() { stream = stream, Rows = Parse(stream, hasHeader, options) }); }
/// <summary> /// Initializes a new instance of the <see cref="CsvRow"/> class. /// </summary> /// <param name="headers"> /// The headers. /// </param> /// <param name="values"> /// The values. /// </param> /// <param name="options"> /// The options. /// </param> // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local public CsvRow(List <string> headers, List <string> values, CsvReaderOptions options) { if (options.StrictCellCount && headers.Count != values.Count) { throw new CsvInvalidCellCountException(headers.Count, values.Count); } for (int i = 0; i < headers.Count; i++) { string header = headers[i]; this.values.Add(header, values.Count > i ? values[i] : string.Empty); } }
/// <summary> /// Parse CSV file to list of dynamic objects. /// </summary> /// <param name="input"> /// The input CSV stream. /// </param> /// <param name="hasHeader"> /// Indicates if the file has a header. /// </param> /// <param name="options"> /// The options. /// </param> /// <returns> /// The list of dynamic objects produced from CSV lines. /// </returns> public static IEnumerable <dynamic> Parse(Stream input, bool hasHeader = true, CsvReaderOptions options = null) { if (options == null) { options = new CsvReaderOptions(); } using (TextReader reader = new StreamReader(input)) { char separator = options.Separator; List <string> headers = new List <string>(); if (hasHeader) { HashSet <string> duplicateHeaderTracker = new HashSet <string>(); var headerRowComponents = CsvParser.ParseLine(reader, options.Separator).ToList(); if (!headerRowComponents.Any()) { yield break; } for (int i = 0; i < headerRowComponents.Count; i++) { string currentHeader = TransformHeaderNameToPropertyName(headerRowComponents[i], options.HeaderMatchRegex ?? MatchSurroundingQuotes); currentHeader = AllowedHeaderNames.IsMatch(currentHeader) ? currentHeader : null; if (options.ResolveHeaderName != null) { var currentHeaderReplacement = options.ResolveHeaderName( headerRowComponents[i], currentHeader); currentHeader = string.IsNullOrEmpty(currentHeaderReplacement) ? currentHeader : currentHeaderReplacement; } if (string.IsNullOrEmpty(currentHeader) || duplicateHeaderTracker.Contains(currentHeader)) { currentHeader = $"Column{i}"; } duplicateHeaderTracker.Add(currentHeader); headers.Add(currentHeader); } } List <string> values = CsvParser.ParseLine(reader, separator).ToList(); while (values.Any()) { if (!headers.Any()) { headers = new List <string>(); var headerCount = values.Count; for (int i = 0; i < headerCount; i++) { headers.Add($"Column{i}"); } } dynamic lineObject = new CsvRow(headers, values, options); yield return(lineObject); values = CsvParser.ParseLine(reader, separator).ToList(); } } }