예제 #1
0
 private static string[] GetHeaders(string line, CsvOptions options)
 {
     return(Trim(SplitLine(line, options), options));
 }
예제 #2
0
 public ReadLine(string[] headers, Dictionary <string, int> headerLookup, int index, string raw, CsvOptions options)
 {
     this.headerLookup = headerLookup;
     this.options      = options;
     Headers           = headers;
     Raw   = raw;
     Index = index;
 }
예제 #3
0
        private static IEnumerable <ICsvLine> ReadImpl(TextReader reader, CsvOptions options)
        {
            if (options == null)
            {
                options = new CsvOptions();
            }

            string line;
            var    index = 0;

            string[] headers = null;
            Dictionary <string, int> headerLookup = null;
            var initalized = false;

            while ((line = reader.ReadLine()) != null)
            {
                index++;
                if (index <= options.RowsToSkip || options.SkipRow?.Invoke(line, index) == true)
                {
                    continue;
                }

                if (!initalized)
                {
                    InitializeOptions(line, options);
                    var skipInitialLine = options.HeaderMode == HeaderMode.HeaderPresent;

                    headers = skipInitialLine ? GetHeaders(line, options) : CreateDefaultHeaders(line, options);

                    try
                    {
                        headerLookup = headers.Select((h, idx) => Tuple.Create(h, idx)).ToDictionary(h => h.Item1, h => h.Item2, options.Comparer);
                    }
                    catch (ArgumentException)
                    {
                        throw new InvalidOperationException("Duplicate headers detected in HeaderPresent mode. If you don't have a header you can set the HeaderMode to HeaderAbsent.");
                    }

                    var aliases = options.Aliases;
                    if (aliases != null)
                    {
                        // NOTE: For each group we need at most 1 match (i.e. SingleOrDefault)
                        foreach (var aliasGroup in aliases)
                        {
                            var groupIndex = -1;
                            foreach (var alias in aliasGroup)
                            {
                                int aliasIndex;
                                if (headerLookup.TryGetValue(alias, out aliasIndex))
                                {
                                    if (groupIndex != -1)
                                    {
                                        throw new InvalidOperationException("Found multiple matches within alias group: " + string.Join(";", aliasGroup));
                                    }

                                    groupIndex = aliasIndex;
                                }
                            }

                            if (groupIndex != -1)
                            {
                                foreach (var alias in aliasGroup)
                                {
                                    headerLookup[alias] = groupIndex;
                                }
                            }
                        }
                    }

                    initalized = true;

                    if (skipInitialLine)
                    {
                        continue;
                    }
                }

                var record = new ReadLine(headers, headerLookup, index, line, options);
                if (options.AllowNewLineInEnclosedFieldValues)
                {
                    while (record.RawSplitLine.Any(f => IsUnterminatedQuotedValue(f, options)))
                    {
                        var nextLine = reader.ReadLine();
                        if (nextLine == null)
                        {
                            break;
                        }
                        line  += options.NewLine + nextLine;
                        record = new ReadLine(headers, headerLookup, index, line, options);
                    }
                }

                yield return(record);
            }
        }