/* * 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(); } } }