/// <summary> /// Reads the row of the CSV file /// </summary> /// <param name="regularDataRow"> /// Set to <c>true</c> if its not the header row and the maximum size should be determined. /// </param> /// <param name="storeWarnings">Set to <c>true</c> if the warnings should be issued.</param> /// <returns> /// <c>NULL</c> if the row can not be read, array of string values representing the columns of /// the row /// </returns> private string[] ReadNextRow(bool regularDataRow, bool storeWarnings) { Restart: // Store the starting Line Number StartLineNumber = EndLineNumber; // If already at end of file, return null if (EndOfFile || CancellationToken.IsCancellationRequested || m_TextReader == null) { return(null); } var item = ReadNextColumn(0, storeWarnings); // An empty line does not have any data if (string.IsNullOrEmpty(item) && m_EndOfLine) { m_EndOfLine = false; if (m_CsvFile.SkipEmptyLines || !regularDataRow) { // go to the next line goto Restart; } // Return it as array of empty columns return(new string[FieldCount]); } // Skip commented lines if (m_CsvFile.FileFormat.CommentLine.Length > 0 && !string.IsNullOrEmpty(item) && item.StartsWith(m_CsvFile.FileFormat.CommentLine, StringComparison.Ordinal) ) // A commented line does start with the comment { if (m_EndOfLine) { m_EndOfLine = false; } else { // it might happen that the comment line contains a Delimiter ReadToEOL(); } goto Restart; } var col = 0; var columns = new List <string>(FieldCount); while (item != null) { // If a column is quoted and does contain the delimiter and linefeed, issue a warning, we // might have an opening delimiter with a missing closing delimiter if (storeWarnings && EndLineNumber > StartLineNumber + 4 && item.Length > 1024 && item.IndexOf(m_CsvFile.FileFormat.FieldDelimiterChar) != -1) { HandleWarning(col, $"Column has {EndLineNumber - StartLineNumber + 1} lines and has a length of {item.Length} characters".AddWarningId()); } if (item.Length == 0) { item = null; } else { if (StringUtils.ShouldBeTreatedAsNull(item, m_CsvFile.TreatTextAsNull)) { item = null; } else { item = item.ReplaceCaseInsensitive(m_CsvFile.FileFormat.NewLinePlaceholder, Environment.NewLine) .ReplaceCaseInsensitive(m_CsvFile.FileFormat.DelimiterPlaceholder, m_CsvFile.FileFormat.FieldDelimiterChar) .ReplaceCaseInsensitive(m_CsvFile.FileFormat.QuotePlaceholder, m_CsvFile.FileFormat.FieldQualifierChar); if (regularDataRow && col < FieldCount) { var column = GetColumn(col); switch (column.DataType) { case DataType.TextToHtml: var newitemE = HTMLStyle.TextToHtmlEncode(item); if (!item.Equals(newitemE, StringComparison.Ordinal)) { HandleWarning(col, $"HTML encoding removed from {item}"); } item = newitemE; break; case DataType.TextToHtmlFull: var newitemS = HTMLStyle.HtmlEncodeShort(item); if (!item.Equals(newitemS, StringComparison.Ordinal)) { HandleWarning(col, $"HTML encoding removed from {item}"); } item = newitemS; break; case DataType.TextPart: var part = GetPart(item, column); if (part == null && item.Length > 0) { HandleWarning(col, $"Part {column.Part} of text {item} is empty."); } item = part; break; } if (!string.IsNullOrEmpty(item) && column.Size < item.Length) { column.Size = item.Length; } } } } columns.Add(item); col++; item = ReadNextColumn(col, storeWarnings); } return(columns.ToArray()); }
protected string TextEncodeField([NotNull] IFileFormat fileFormat, object dataObject, [NotNull] WriterColumn columnInfo, bool isHeader, [CanBeNull] IDataReader reader, [CanBeNull] Func <string, DataType, IFileFormat, string> handleQualify) { if (columnInfo is null) { throw new ArgumentNullException(nameof(columnInfo)); } if (fileFormat.IsFixedLength && columnInfo.FieldLength == 0) { throw new FileWriterException("For fix length output the length of the columns needs to be specified."); } string displayAs; if (isHeader) { if (dataObject is null) { throw new ArgumentNullException(nameof(dataObject)); } displayAs = dataObject.ToString(); } else { try { if (dataObject == null || dataObject is DBNull) { displayAs = columnInfo.ValueFormat.DisplayNullAs; } else { switch (columnInfo.ValueFormat.DataType) { case DataType.Integer: displayAs = Convert.ToInt64(dataObject).ToString(columnInfo.ValueFormat.NumberFormat, CultureInfo.InvariantCulture).Replace( CultureInfo.InvariantCulture.NumberFormat.NumberGroupSeparator, columnInfo.ValueFormat.GroupSeparator); break; case DataType.Boolean: displayAs = (bool)dataObject ? columnInfo.ValueFormat.True : columnInfo.ValueFormat.False; break; case DataType.Double: displayAs = StringConversion.DoubleToString( dataObject is double d ? d : Convert.ToDouble(dataObject.ToString(), CultureInfo.InvariantCulture), columnInfo.ValueFormat); break; case DataType.Numeric: displayAs = StringConversion.DecimalToString( dataObject is decimal @decimal ? @decimal : Convert.ToDecimal(dataObject.ToString(), CultureInfo.InvariantCulture), columnInfo.ValueFormat); break; case DataType.DateTime: displayAs = reader == null ? StringConversion.DateTimeToString((DateTime)dataObject, columnInfo.ValueFormat) : StringConversion.DateTimeToString(HandleTimeZone((DateTime)dataObject, columnInfo, reader), columnInfo.ValueFormat); break; case DataType.Guid: // 382c74c3-721d-4f34-80e5-57657b6cbc27 displayAs = ((Guid)dataObject).ToString(); break; case DataType.String: case DataType.TextToHtml: case DataType.TextToHtmlFull: case DataType.TextPart: displayAs = dataObject.ToString(); if (columnInfo.ValueFormat.DataType == DataType.TextToHtml) { displayAs = HTMLStyle.TextToHtmlEncode(displayAs); } // a new line of any kind will be replaced with the placeholder if set if (fileFormat.NewLinePlaceholder.Length > 0) { displayAs = StringUtils.HandleCRLFCombinations(displayAs, fileFormat.NewLinePlaceholder); } if (fileFormat.DelimiterPlaceholder.Length > 0 && fileFormat.FieldDelimiterChar != '\0') { displayAs = displayAs.Replace(fileFormat.FieldDelimiterChar.ToStringHandle0(), fileFormat.DelimiterPlaceholder); } if (fileFormat.QuotePlaceholder.Length > 0 && fileFormat.FieldQualifierChar != '\0') { displayAs = displayAs.Replace(fileFormat.FieldQualifierChar.ToStringHandle0(), fileFormat.QuotePlaceholder); } break; default: displayAs = string.Empty; break; } } } catch (Exception ex) { // In case a cast did fail (eg.g trying to format as integer and providing a text, use the // original value displayAs = dataObject?.ToString() ?? string.Empty; if (string.IsNullOrEmpty(displayAs)) { HandleError(columnInfo.Name, ex.Message); } else { HandleWarning(columnInfo.Name, "Value stored as: " + displayAs + $"\nExpected {columnInfo.ValueFormat.DataType} but was {dataObject?.GetType()}" + ex.Message); } } } // Adjust the output in case its is fixed length if (fileFormat.IsFixedLength) { if (displayAs.Length <= columnInfo.FieldLength || columnInfo.FieldLength <= 0) { return(displayAs.PadRight(columnInfo.FieldLength, ' ')); } HandleWarning(columnInfo.Name, $"Text with length of {displayAs.Length} has been cut off after {columnInfo.FieldLength} character"); return(displayAs.Substring(0, columnInfo.FieldLength)); } // Qualify text if required if (fileFormat.FieldQualifierChar != '\0' && handleQualify != null) { return(handleQualify(displayAs, columnInfo.ValueFormat.DataType, fileFormat)); } return(displayAs); }