/*
* 2006 - 2018 Ted Spence, http://tedspence.com
* License: http://www.apache.org/licenses/LICENSE-2.0
* Home page: https://github.com/tspence/csharp-csv-reader
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Data;
using System.Reflection;
#if HAS_ASYNC
using System.Threading.Tasks;
#endif
// ReSharper disable LoopCanBeConvertedToQuery
// ReSharper disable ConvertIfStatementToNullCoalescingExpression
namespace CSVNET
{
///
/// Helper object that implements serialization separately from the string or stream I/O
///
///
public class SerializationHelper where T : class, new()
{
private readonly CSVSettings _settings;
private readonly PropertyInfo[] _properties;
private readonly FieldInfo[] _fields;
private readonly char[] _riskyChars;
private readonly Dictionary _forceQualifierTypes;
///
/// Constructs a serialization helper object separate from I/O
///
///
///
///
public SerializationHelper(CSVSettings settings, char[] riskyChars, Dictionary forceQualifierTypes)
{
_settings = settings;
if (_settings == null)
{
_settings = CSVSettings.CSV;
}
// Extract properties and fields that are not excluded
var excluded = new ExcludedColumnHelper(_settings);
var props = new List();
foreach (var prop in typeof(T).GetProperties())
{
if (!excluded.IsExcluded(prop.Name))
{
props.Add(prop);
}
}
var fields = new List();
foreach (var field in typeof(T).GetFields())
{
if (!excluded.IsExcluded(field.Name))
{
fields.Add(field);
}
}
_properties = props.ToArray();
_fields = fields.ToArray();
_riskyChars = riskyChars;
_forceQualifierTypes = forceQualifierTypes;
}
///
/// Serialize the header for the CSV file
///
///
public string SerializeHeader()
{
var headers = new List();
foreach (var field in _fields)
{
headers.Add(field.Name);
}
foreach (var prop in _properties)
{
headers.Add(prop.Name);
}
return CSV.ItemsToCsv(headers, _settings, _riskyChars, _forceQualifierTypes);
}
///
/// Serialize a single row for the CSV file
///
///
///
public string Serialize(T obj)
{
var items = new List();
foreach (var field in _fields)
{
items.Add(field.GetValue(obj));
}
foreach (var prop in _properties)
{
items.Add(prop.GetValue(obj, null));
}
return CSV.ItemsToCsv(items, _settings, _riskyChars, _forceQualifierTypes);
}
}
///
/// Writes CSV objects to a stream
///
public class CSVWriter : IDisposable
{
private readonly CSVSettings _settings;
private readonly StreamWriter _writer;
private readonly char[] _riskyChars;
private readonly Dictionary _forceQualifierTypes;
///
/// Construct a new CSV writer to produce output on the enclosed StreamWriter
///
/// The stream where this CSV will be outputted
/// The CSV settings to use when writing to the stream (Default: CSV)
public CSVWriter(StreamWriter dest, CSVSettings settings = null)
{
_writer = dest;
_settings = settings;
if (_settings == null)
{
_settings = CSVSettings.CSV;
}
_riskyChars = _settings.GetRiskyChars();
_forceQualifierTypes = _settings.GetForceQualifierTypes();
}
///
/// Construct a new CSV writer to produce output on the enclosed stream
///
/// The stream where this CSV will be outputted
/// The CSV settings to use when writing to the stream (Default: CSV)
public CSVWriter(Stream dest, CSVSettings settings = null)
{
_settings = settings;
if (_settings == null)
{
_settings = CSVSettings.CSV;
}
_writer = new StreamWriter(dest, _settings.Encoding);
_riskyChars = _settings.GetRiskyChars();
_forceQualifierTypes = _settings.GetForceQualifierTypes();
}
///
/// Write the data table to a stream in CSV format
///
/// The data table to write
public void Write(DataTable dt)
{
if (_settings.HeaderRowIncluded)
{
var headers = new List();
foreach (DataColumn col in dt.Columns)
{
headers.Add(col.ColumnName);
}
_writer.Write(CSV.ItemsToCsv(headers, _settings, _riskyChars, _forceQualifierTypes));
_writer.Write(_settings.LineSeparator);
}
foreach (DataRow dr in dt.Rows)
{
_writer.Write(CSV.ItemsToCsv(dr.ItemArray, _settings, _riskyChars, _forceQualifierTypes));
_writer.Write(_settings.LineSeparator);
}
}
///
/// Write a single line to this CSV
///
///
public void WriteLine(IEnumerable items)
{
_writer.Write(CSV.ItemsToCsv(items, _settings, _riskyChars, _forceQualifierTypes));
_writer.Write(_settings.LineSeparator);
}
#if HAS_ASYNC
///
/// Write a single line to this CSV
///
///
public async Task WriteLineAsync(IEnumerable items)
{
await _writer.WriteAsync(CSV.ItemsToCsv(items, _settings, _riskyChars, _forceQualifierTypes));
await _writer.WriteAsync(_settings.LineSeparator);
}
///
/// Write the data table to a stream in CSV format
///
/// The data table to write
public async Task WriteAsync(DataTable dt)
{
if (_settings.HeaderRowIncluded)
{
var headers = new List();
foreach (DataColumn col in dt.Columns)
{
headers.Add(col.ColumnName);
}
await _writer.WriteAsync(CSV.ItemsToCsv(headers, _settings, _riskyChars, _forceQualifierTypes));
await _writer.WriteAsync(_settings.LineSeparator);
}
foreach (DataRow dr in dt.Rows)
{
await _writer.WriteAsync(CSV.ItemsToCsv(dr.ItemArray, _settings, _riskyChars, _forceQualifierTypes));
await _writer.WriteAsync(_settings.LineSeparator);
}
}
#endif
///
/// Serialize a list of objects to CSV using this writer
///
/// An IEnumerable that produces the list of objects to serialize.
public void Serialize(IEnumerable list) where T : class, new()
{
var serializer = new SerializationHelper(_settings, _riskyChars, _forceQualifierTypes);
if (_settings.HeaderRowIncluded)
{
_writer.Write(serializer.SerializeHeader());
_writer.Write(_settings.LineSeparator);
}
foreach (var row in list)
{
_writer.Write(serializer.Serialize(row));
_writer.Write(_settings.LineSeparator);
}
}
#if HAS_ASYNC
///
/// Serialize a list of objects to CSV using this writer
///
/// An IEnumerable that produces the list of objects to serialize.
public async Task SerializeAsync(IEnumerable list) where T : class, new()
{
var serializer = new SerializationHelper(_settings, _riskyChars, _forceQualifierTypes);
if (_settings.HeaderRowIncluded)
{
await _writer.WriteAsync(serializer.SerializeHeader());
await _writer.WriteAsync(_settings.LineSeparator);
}
foreach (var row in list)
{
await _writer.WriteAsync(serializer.Serialize(row));
await _writer.WriteAsync(_settings.LineSeparator);
}
}
#endif
#if HAS_ASYNC_IENUM
///
/// Serialize a list of objects to CSV using this writer
///
/// An IEnumerable that produces the list of objects to serialize.
public async Task SerializeAsync(IAsyncEnumerable list) where T : class, new()
{
var serializer = new SerializationHelper(_settings, _riskyChars, _forceQualifierTypes);
if (_settings.HeaderRowIncluded)
{
await _writer.WriteAsync(serializer.SerializeHeader());
await _writer.WriteAsync(_settings.LineSeparator);
}
await foreach (var row in list)
{
await _writer.WriteAsync(serializer.Serialize(row));
await _writer.WriteAsync(_settings.LineSeparator);
}
}
#endif
///
/// Close our resources - specifically, the stream reader
///
public void Dispose()
{
_writer.Close();
_writer.Dispose();
}
}
}