Created
February 26, 2015 01:29
-
-
Save josephrodriguez/11b676f166211f5927df to your computer and use it in GitHub Desktop.
Generic CSV writer.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
namespace Example | |
{ | |
public class CsvWriter<T> : IDisposable | |
{ | |
private readonly StreamWriter _writer; | |
private readonly List<string> _headers; | |
private readonly IDictionary<Type, List<Func<object, string>>> _formatters; | |
private CsvWriter() | |
{ | |
_headers = typeof(T).GetProperties() | |
.Select(p => p.Name) | |
.ToList(); | |
_formatters = new Dictionary<Type, List<Func<object, string>>>(); | |
} | |
public CsvWriter(string path) | |
:this() | |
{ | |
_writer = new StreamWriter(path); | |
} | |
public CsvWriter(Stream stream) | |
:this() | |
{ | |
_writer = new StreamWriter(stream); | |
} | |
public void WriteRow(T element) | |
{ | |
var row = GetRow(element); | |
_writer.WriteLine(row); | |
} | |
public void WriteRows(IEnumerable<T> elements) | |
{ | |
foreach (var element in elements) | |
WriteRow(element); | |
} | |
public void AddFormatter<V>(Func<V, string> formatter) | |
{ | |
if(!_formatters.ContainsKey(typeof(V))) | |
_formatters.Add(typeof(V), new List<Func<object, string>>()); | |
_formatters[typeof(V)].Add(o => formatter((V) o)); | |
} | |
public void WriteHeaders() | |
{ | |
var headersLine = string.Join(",", _headers.Select(FormatCamelCase)); | |
_writer.WriteLine(headersLine); | |
} | |
public void Close() | |
{ | |
_writer.Close(); | |
} | |
public void Flush() | |
{ | |
_writer.Flush(); | |
} | |
public void Dispose() | |
{ | |
_writer.Dispose(); | |
} | |
private string GetRow(T element) | |
{ | |
var values = _headers.Select(typeof (T).GetProperty) | |
.Select(property => property == null | |
? string.Empty | |
: Encode(property.PropertyType, property.GetValue(element))) | |
.ToList(); | |
return string.Join(",", values); | |
} | |
private string Encode(Type type, object value) | |
{ | |
if (value == null) | |
return string.Empty; | |
if (_formatters.ContainsKey(type)) | |
{ | |
var formatter = _formatters[type].FirstOrDefault(); | |
if (formatter != null) | |
return formatter.Invoke(value); | |
} | |
var result = value.ToString(); | |
if (result.Contains(",") || result.Contains("\"")) | |
result = '"' + result.Replace("\"", "\"\"") + '"'; | |
return result; | |
} | |
public string FormatCamelCase(string s) | |
{ | |
var b = new StringBuilder(); | |
var j = 0; | |
for (var i = 0; i < s.Length; i++) | |
{ | |
b.Append(s[i]); | |
if (char.IsUpper(s[i])) | |
b.Insert(i + j++, ' '); | |
} | |
return b.ToString().TrimStart(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment