/// <summary> /// Stores that data in the given stream. /// </summary> /// <param name="reader">The data reader.</param> /// <param name="writer">The writer.</param> /// <param name="readerFileSetting">The file.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// Number of rows written /// </returns> protected void DataReader2Stream(IDataReader reader, TextWriter writer, CancellationToken cancellationToken) { Contract.Requires(reader != null); Contract.Requires(writer != null); var columnInfos = GetColumnInformation(reader); var enumerable = columnInfos.ToList(); if (enumerable.IsEmpty()) { throw new ApplicationException("No columns defined to be written."); } var recordEnd = m_StructuredWriterFile.FileFormat.NewLine.Replace("CR", "\r").Replace("LF", "\n").Replace(" ", "") .Replace("\t", ""); HandleWriteStart(); var numEmptyRows = 0; var numColumns = enumerable.Count(); var sb = new StringBuilder(1024); // Assume a capacity of 1024 characters to start , data is flushed every 512 chars if (!string.IsNullOrEmpty(m_StructuredWriterFile.Header)) { sb.Append(ReplacePlaceHolder(m_StructuredWriterFile.Header)); if (!m_StructuredWriterFile.Header.EndsWith(recordEnd, StringComparison.Ordinal)) { sb.Append(recordEnd); } } var withHeader = m_StructuredWriterFile.Row; var colNum = 0; foreach (var columnInfo in enumerable) { var placeHolder = string.Format(System.Globalization.CultureInfo.CurrentCulture, cHeaderPlaceholder, colNum); if (m_StructuredWriterFile.XMLEncode) { withHeader = withHeader.Replace(placeHolder, HTMLStyle.XmlElementName(columnInfo.Header)); } else if (m_StructuredWriterFile.JSONEncode) { withHeader = withHeader.Replace(placeHolder, HTMLStyle.JsonElementName(columnInfo.Header)); } else { withHeader = withHeader.Replace(placeHolder, columnInfo.Header); } colNum++; } withHeader = withHeader.Trim(); while (reader.Read() && !cancellationToken.IsCancellationRequested) { NextRecord(); if (sb.Length > 512) { writer.Write(sb.ToString()); sb.Length = 0; } // Start a new line sb.Append(recordEnd); var emptyColumns = 0; var row = withHeader; colNum = 0; foreach (var columnInfo in enumerable) { Contract.Assume(columnInfo != null); var placeHolder1 = string.Format(System.Globalization.CultureInfo.CurrentCulture, cFieldPlaceholderByNumber, colNum); var value = string.Empty; var placeHolder2 = string.Format(System.Globalization.CultureInfo.CurrentCulture, cFieldPlaceholderByName, columnInfo.Header); var col = reader.GetValue(columnInfo.ColumnOridinalReader); if (col == DBNull.Value) { emptyColumns++; } else { value = TextEncodeField(m_StructuredWriterFile.FileFormat, col, columnInfo, false, reader, null); if (m_StructuredWriterFile.XMLEncode) { value = SecurityElement.Escape(value); } else if (m_StructuredWriterFile.JSONEncode) { value = HTMLStyle.JsonEncode(value); } } row = row.Replace(placeHolder1, value).Replace(placeHolder2, value); colNum++; } if (emptyColumns == numColumns) { numEmptyRows++; } else { sb.Append(row); numEmptyRows = 0; } } sb.Append(ReplacePlaceHolder(m_StructuredWriterFile.Footer)); writer.Write(sb.ToString()); }
/// <summary> /// Writes the specified file reading from the given reader /// </summary> /// <param name="reader">A Data Reader with the data</param> /// <param name="output">The output.</param> /// <param name="cancellationToken">The cancellation token.</param> protected override async Task WriteReaderAsync([NotNull] IFileReader reader, [NotNull] Stream output, CancellationToken cancellationToken) { using (var writer = new StreamWriter(output, new UTF8Encoding(true), 4096)) { SetColumns(reader); var numColumns = Columns.Count(); if (numColumns == 0) { throw new FileWriterException("No columns defined to be written."); } var recordEnd = NewLine; HandleWriteStart(); // Header if (!string.IsNullOrEmpty(Header)) { var sbH = new StringBuilder(); sbH.Append(Header); if (!Header.EndsWith(recordEnd, StringComparison.Ordinal)) { sbH.Append(recordEnd); } await writer.WriteAsync(sbH.ToString()).ConfigureAwait(false); } // Static template for the row, built once var withHeader = m_Row; var colNum = 0; var placeHolderLookup1 = new Dictionary <int, string>(); var placeHolderLookup2 = new Dictionary <int, string>(); foreach (var columnInfo in Columns) { var placeHolder = string.Format(CultureInfo.CurrentCulture, c_HeaderPlaceholder, colNum); if (m_XMLEncode) { withHeader = withHeader.Replace(placeHolder, HTMLStyle.XmlElementName(columnInfo.Name)); } else if (m_JSONEncode) { withHeader = withHeader.Replace(placeHolder, HTMLStyle.JsonElementName(columnInfo.Name)); } else { withHeader = withHeader.Replace(placeHolder, columnInfo.Name); } placeHolderLookup1.Add(colNum, string.Format(CultureInfo.CurrentCulture, c_FieldPlaceholderByNumber, colNum)); placeHolderLookup2.Add(colNum, string.Format(CultureInfo.CurrentCulture, cFieldPlaceholderByName, columnInfo.Name)); colNum++; } withHeader = withHeader.Trim(); var sb = new StringBuilder( 1024); // Assume a capacity of 1024 characters to start, data is flushed every 512 chars while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false) && !cancellationToken.IsCancellationRequested) { NextRecord(); // Start a new line sb.Append(recordEnd); var row = withHeader; colNum = 0; foreach (var value in from columnInfo in Columns let col = reader.GetValue(columnInfo.ColumnOrdinal) select m_XMLEncode ? SecurityElement.Escape(TextEncodeField(FileFormat, col, columnInfo, false, reader, null)) : JsonConvert.ToString(col)) { row = row.Replace(placeHolderLookup1[colNum], value).Replace(placeHolderLookup2[colNum], value); colNum++; } sb.Append(row); if (sb.Length <= 512) { continue; } await writer.WriteAsync(sb.ToString()).ConfigureAwait(false); sb.Length = 0; } if (sb.Length > 0) { await writer.WriteAsync(sb.ToString()).ConfigureAwait(false); } // Footer if (!string.IsNullOrEmpty(Footer())) { await writer.WriteAsync(Footer()).ConfigureAwait(false); } await writer.FlushAsync(); } }