using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Swan.Reflection;
namespace Swan.Formatters {
///
/// A CSV writer useful for exporting a set of objects.
///
///
/// The following code describes how to save a list of objects into a CSV file.
///
/// using System.Collections.Generic;
/// using Swan.Formatters;
///
/// class Example
/// {
/// class Person
/// {
/// public string Name { get; set; }
/// public int Age { get; set; }
/// }
///
/// static void Main()
/// {
/// // create a list of people
/// var people = new List<Person>
/// {
/// new Person { Name = "Artyom", Age = 20 },
/// new Person { Name = "Aloy", Age = 18 }
/// }
///
/// // write items inside file.csv
/// CsvWriter.SaveRecords(people, "C:\\Users\\user\\Documents\\file.csv");
///
/// // output
/// // | Name | Age |
/// // | Artyom | 20 |
/// // | Aloy | 18 |
/// }
/// }
///
///
public class CsvWriter : IDisposable {
private static readonly PropertyTypeCache TypeCache = new PropertyTypeCache();
private readonly Object _syncLock = new Object();
private readonly Stream _outputStream;
private readonly Encoding _encoding;
private readonly Boolean _leaveStreamOpen;
private Boolean _isDisposing;
private UInt64 _mCount;
#region Constructors
///
/// Initializes a new instance of the class.
///
/// The output stream.
/// if set to true [leave open].
/// The encoding.
public CsvWriter(Stream outputStream, Boolean leaveOpen, Encoding encoding) {
this._outputStream = outputStream;
this._encoding = encoding;
this._leaveStreamOpen = leaveOpen;
}
///
/// Initializes a new instance of the class.
/// It automatically closes the stream when disposing this writer.
///
/// The output stream.
/// The encoding.
public CsvWriter(Stream outputStream, Encoding encoding) : this(outputStream, false, encoding) {
// placeholder
}
///
/// Initializes a new instance of the class.
/// It uses the Windows 1252 encoding and automatically closes
/// the stream upon disposing this writer.
///
/// The output stream.
public CsvWriter(Stream outputStream) : this(outputStream, false, Definitions.Windows1252Encoding) {
// placeholder
}
///
/// Initializes a new instance of the class.
/// It opens the file given file, automatically closes the stream upon
/// disposing of this writer, and uses the Windows 1252 encoding.
///
/// The filename.
public CsvWriter(String filename) : this(File.OpenWrite(filename), false, Definitions.Windows1252Encoding) {
// placeholder
}
///
/// Initializes a new instance of the class.
/// It opens the file given file, automatically closes the stream upon
/// disposing of this writer, and uses the given text encoding for output.
///
/// The filename.
/// The encoding.
public CsvWriter(String filename, Encoding encoding) : this(File.OpenWrite(filename), false, encoding) {
// placeholder
}
#endregion
#region Properties
///
/// Gets or sets the field separator character.
///
///
/// The separator character.
///
public Char SeparatorCharacter { get; set; } = ',';
///
/// Gets or sets the escape character to use to escape field values.
///
///
/// The escape character.
///
public Char EscapeCharacter { get; set; } = '"';
///
/// Gets or sets the new line character sequence to use when writing a line.
///
///
/// The new line sequence.
///
public String NewLineSequence { get; set; } = Environment.NewLine;
///
/// Defines a list of properties to ignore when outputting CSV lines.
///
///
/// The ignore property names.
///
public List IgnorePropertyNames { get; } = new List();
///
/// Gets number of lines that have been written, including the headings line.
///
///
/// The count.
///
public UInt64 Count {
get {
lock(this._syncLock) {
return this._mCount;
}
}
}
#endregion
#region Helpers
///
/// Saves the items to a stream.
/// It uses the Windows 1252 text encoding for output.
///
/// The type of enumeration.
/// The items.
/// The stream.
/// true if stream is truncated, default false.
/// Number of item saved.
public static Int32 SaveRecords(IEnumerable items, Stream stream, Boolean truncateData = false) {
// truncate the file if it had data
if(truncateData && stream.Length > 0) {
stream.SetLength(0);
}
using CsvWriter writer = new CsvWriter(stream);
writer.WriteHeadings();
writer.WriteObjects(items);
return (Int32)writer.Count;
}
///
/// Saves the items to a CSV file.
/// If the file exits, it overwrites it. If it does not, it creates it.
/// It uses the Windows 1252 text encoding for output.
///
/// The type of enumeration.
/// The items.
/// The file path.
/// Number of item saved.
public static Int32 SaveRecords(IEnumerable items, String filePath) => SaveRecords(items, File.OpenWrite(filePath), true);
#endregion
#region Generic, main Write Line Method
///
/// Writes a line of CSV text. Items are converted to strings.
/// If items are found to be null, empty strings are written out.
/// If items are not string, the ToStringInvariant() method is called on them.
///
/// The items.
public void WriteLine(params Object[] items) => this.WriteLine(items.Select(x => x == null ? String.Empty : x.ToStringInvariant()));
///
/// Writes a line of CSV text. Items are converted to strings.
/// If items are found to be null, empty strings are written out.
/// If items are not string, the ToStringInvariant() method is called on them.
///
/// The items.
public void WriteLine(IEnumerable