/// <summary> /// Asynchronously writes all rows in <paramref name="this"/> to <paramref name="csvWriter"/>. /// </summary> /// <remarks> /// </remarks> /// <param name="this"> /// The <see cref="DataTable"/>. /// </param> /// <param name="csvWriter"> /// The <see cref="CsvWriter"/>. /// </param> /// <param name="writeHeaderRecord"> /// If <see langword="true"/>, a header record will also be written, which will be comprised of the column names defined for <paramref name="this"/>. /// </param> /// <param name="maximumRows"> /// The maximum number of rows from <paramref name="this"/> that should be written to <paramref name="csvWriter"/>. /// </param> /// <param name="objectToStringConverter"> /// Provides a means of converting values in the <see cref="DataRow"/>s to <see cref="String"/>s. /// </param> /// <returns> /// The actual number of rows from <paramref name="this"/> written to <paramref name="csvWriter"/>. /// </returns> public async static Task <int> WriteCsvAsync(this DataTable @this, CsvWriter csvWriter, bool writeHeaderRecord, int?maximumRows, Func <object, string> objectToStringConverter) { @this.AssertNotNull("@this"); csvWriter.AssertNotNull("csvWriter"); objectToStringConverter.AssertNotNull("objectToStringConverter"); var num = 0; if (writeHeaderRecord) { var columnNames = new string[@this.Columns.Count]; for (var i = 0; i < columnNames.Length; ++i) { columnNames[i] = @this.Columns[i].ColumnName; } await csvWriter.WriteRecordAsync(columnNames).ConfigureAwait(false); } var maximum = maximumRows.GetValueOrDefault(int.MaxValue); var buffer = new DataRecord[16]; var bufferOffset = 0; foreach (DataRow row in @this.Rows) { var record = new DataRecord(); for (var i = 0; i < row.ItemArray.Length; ++i) { record.Add(objectToStringConverter(row.ItemArray[i])); } buffer[bufferOffset++] = record; if (bufferOffset == buffer.Length) { // buffer full await csvWriter.WriteRecordsAsync(buffer, 0, buffer.Length).ConfigureAwait(false); bufferOffset = 0; } if (++num == maximum) { break; } } // write any outstanding data in buffer await csvWriter.WriteRecordsAsync(buffer, 0, bufferOffset).ConfigureAwait(false); return(num); }
public void issue12693_repro() { var recordCount = 50; var random = new Random(); var memoryStream = new MemoryStream(); var csvWriter = new CsvWriter(memoryStream); // create some dummy data to work with for (var record = 0; record < recordCount; ++record) { var dataRecord = new DataRecord(null); for (var value = 0; value < random.Next(100, 200); ++value) { dataRecord.Add("value" + random.Next(0, 100000)); } csvWriter.WriteRecord(dataRecord); } memoryStream.Position = 0; // create a fake server that will feed us our dummy data in dribs and drabs using (var fakeServer = new FakeServer(memoryStream)) using (var connectionToServer = new TcpClient("localhost", FakeServer.Port)) using (var csvReader = new CsvReader(connectionToServer.GetStream())) { while (csvReader.HasMoreRecords) { csvReader.ReadDataRecord(); } // when the bug manifests itself, the parser may stop parsing prematurely so the record counts won't match // see below for an explanation of how the bug is triggered Assert.Equal(recordCount, csvReader.RecordNumber); } }
/// <summary> /// Asynchronously writes all rows in <paramref name="this"/> to <paramref name="csvWriter"/>. /// </summary> /// <remarks> /// </remarks> /// <param name="this"> /// The <see cref="DataTable"/>. /// </param> /// <param name="csvWriter"> /// The <see cref="CsvWriter"/>. /// </param> /// <param name="writeHeaderRecord"> /// If <see langword="true"/>, a header record will also be written, which will be comprised of the column names defined for <paramref name="this"/>. /// </param> /// <param name="maximumRows"> /// The maximum number of rows from <paramref name="this"/> that should be written to <paramref name="csvWriter"/>. /// </param> /// <param name="objectToStringConverter"> /// Provides a means of converting values in the <see cref="DataRow"/>s to <see cref="String"/>s. /// </param> /// <returns> /// The actual number of rows from <paramref name="this"/> written to <paramref name="csvWriter"/>. /// </returns> public async static Task<int> WriteCsvAsync(this DataTable @this, CsvWriter csvWriter, bool writeHeaderRecord, int? maximumRows, Func<object, string> objectToStringConverter) { @this.AssertNotNull("@this"); csvWriter.AssertNotNull("csvWriter"); objectToStringConverter.AssertNotNull("objectToStringConverter"); var num = 0; if (writeHeaderRecord) { var columnNames = new string[@this.Columns.Count]; for (var i = 0; i < columnNames.Length; ++i) { columnNames[i] = @this.Columns[i].ColumnName; } await csvWriter.WriteRecordAsync(columnNames).ConfigureAwait(false); } var maximum = maximumRows.GetValueOrDefault(int.MaxValue); var buffer = new DataRecord[16]; var bufferOffset = 0; foreach (DataRow row in @this.Rows) { var record = new DataRecord(); for (var i = 0; i < row.ItemArray.Length; ++i) { record.Add(objectToStringConverter(row.ItemArray[i])); } buffer[bufferOffset++] = record; if (bufferOffset == buffer.Length) { // buffer full await csvWriter.WriteRecordsAsync(buffer, 0, buffer.Length).ConfigureAwait(false); bufferOffset = 0; } if (++num == maximum) { break; } } // write any outstanding data in buffer await csvWriter.WriteRecordsAsync(buffer, 0, bufferOffset).ConfigureAwait(false); return num; }