public IEnumerable<Record> ReadFrom(Stream stream, string fieldSeparator = ",", string recordSeparator = "\r\n", bool supportQuotedFields = true, bool hasHeaderRow = false, IDictionary<string, Func<string, object>> namedFieldConverters = null, IDictionary<int, Func<string, object>> indexedFieldConverters = null) { if (stream == null) { throw new ArgumentException(ErrorNoStream); } if (fieldSeparator == null) { fieldSeparator = ""; } if (recordSeparator == null) { recordSeparator = ""; } if (fieldSeparator == recordSeparator) { throw new ParseException(ErrorFieldSeparatorAndRecordSeparator); } if (namedFieldConverters != null && indexedFieldConverters != null) { throw new ArgumentException(ErrorBothNamedAndIndexedFieldConverters); } if (namedFieldConverters != null && !hasHeaderRow) { throw new ArgumentException(ErrorNamedFieldConverters); } var bufferedStream = new BufferedStream(stream, 131072); var fieldValues = new List<object>(); var parseContext = new ParseContext { HeaderRowFieldIndexes = new Dictionary<string, int>(), HasHeaderRow = hasHeaderRow, RecordSeparator = recordSeparator, FieldSeparator = fieldSeparator, ReadingHeaderRow = hasHeaderRow, Handle = StartReadField, RecordNumber = 1, SupportQuotedFields = supportQuotedFields, Capture = new StringBuilder(), NamedFieldConverters = namedFieldConverters, IndexedFieldConverters = indexedFieldConverters, StringCache = new Dictionary<string, string>() }; var specialTokens = new List<string>(); if (!String.IsNullOrEmpty(fieldSeparator)) { specialTokens.Add(fieldSeparator); } if (!String.IsNullOrEmpty(recordSeparator)) { specialTokens.Add(recordSeparator); } if (supportQuotedFields) { specialTokens.Add("\""); } var specialChars = specialTokens.SelectMany(x => x).Distinct().ToArray(); foreach (var token in _streamTokenizer.Tokenize(bufferedStream, specialChars)) { var yieldIt = parseContext.Handle(token, fieldValues, parseContext); if (yieldIt) { yield return new Record(fieldValues, parseContext.HeaderRowFieldIndexes); fieldValues = new List<object>(parseContext.HasHeaderRow ? parseContext.HeaderRowFieldIndexes.Count : fieldValues.Count); parseContext.Capture.Length = 0; } } if (parseContext.Handle == ReadQuotedField) { throw new ParseException(string.Format(ErrorQuotedFieldDoesNotHaveACloseQuoteOnLineField, parseContext.RecordNumber, parseContext.FieldNumber)); } if (parseContext.ReadingQuotedField && (parseContext.Handle == ContinueCollectFieldSeparator || parseContext.Handle == ContinueCollectRecordSeparator)) { ThrowUnescapedQuoteException(parseContext); } if (parseContext.Capture.Length > 0 || parseContext.FieldNumber > 0 && (parseContext.Handle == StartReadField || parseContext.Handle == BranchReadEscapedQuoteOrStartCollectingSeparator)) { if (parseContext.Handle == StartReadField) { parseContext.IncrementFieldNumber(); } AddFieldValue(fieldValues, parseContext); } parseContext.StringCache = null; if (fieldValues.Count > 0) { yield return new Record(fieldValues, parseContext.HeaderRowFieldIndexes); } }
private bool StartReadField(Token token, List<object> fieldValues, ParseContext parseContext) { if (!(token is EndOfStreamToken)) { parseContext.IncrementFieldNumber(); if (parseContext.SupportQuotedFields && token.Value.Equals("\"") && token is SpecialToken) { parseContext.ReadingQuotedField = true; parseContext.Handle = ReadQuotedField; } else { parseContext.ReadingQuotedField = false; parseContext.Handle = ReadUnquotedField; return ReadUnquotedField(token, fieldValues, parseContext); } } return false; }