Created
January 15, 2015 14:41
-
-
Save mariodivece/e9aa7d628ac4ef16f09e to your computer and use it in GitHub Desktop.
CSV Writer
This file contains hidden or 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
namespace Unosquare.Utils | |
{ | |
using System; | |
using System.Collections.Concurrent; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Text; | |
using System.Threading.Tasks; | |
/// <summary> | |
/// Represents a simple exporter for CSV. | |
/// </summary> | |
public class CsvWriter : IDisposable | |
{ | |
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> TypeCache = new ConcurrentDictionary<Type, PropertyInfo[]>(); | |
private Stream OutputStream = null; | |
private Encoding Encoding = null; | |
public string Separator { get; set; } | |
public List<string> IgnoreProperties { get; private set; } | |
public string EndOfLine { get; set; } | |
private CsvWriter() | |
{ | |
this.Separator = ","; | |
this.IgnoreProperties = new List<string>(); | |
} | |
public CsvWriter(Stream outputStream, Encoding encoding) | |
: this() | |
{ | |
this.OutputStream = outputStream; | |
this.Encoding = encoding; | |
this.EndOfLine = "\r\n"; | |
} | |
public async Task WriteLineAsync(object item) | |
{ | |
var properties = GetFilteredProperties(item.GetType()); | |
var valuesList = new List<object>(); | |
foreach (var property in properties) | |
{ | |
try | |
{ | |
var value = property.GetValue(item, null); | |
valuesList.Add(value); | |
} | |
catch | |
{ | |
valuesList.Add(null); | |
} | |
} | |
await WriteValuesAsync(valuesList.ToArray()); | |
} | |
public async Task WriteHeaderAsync(Type type) | |
{ | |
var properties = GetFilteredProperties(type); | |
var valuesList = properties.Select(p => p.Name).ToArray(); | |
await WriteValuesAsync(valuesList); | |
} | |
public async Task WriteHeaderAsync<T>() | |
{ | |
await WriteHeaderAsync(typeof(T)); | |
} | |
public async Task WriteValuesAsync(object[] values) | |
{ | |
var length = values.Count(); | |
var separatorBytes = Encoding.GetBytes(Separator); | |
var endOfLineBytes = Encoding.GetBytes(EndOfLine); | |
for (var i = 0; i < length; i++) | |
{ | |
var value = values[i]; | |
var stringVal = value == null ? string.Empty : value.ToString(); | |
var enclose = stringVal.IndexOf(',') >= 0 || stringVal.IndexOf('"') >= 0; | |
stringVal = stringVal.Replace("\"", "\"\""); | |
if (enclose) stringVal = string.Format("\"{0}\"", stringVal); | |
var output = Encoding.GetBytes(stringVal); | |
await this.OutputStream.WriteAsync(output, 0, output.Length); | |
if (i < length - 1) | |
await this.OutputStream.WriteAsync(separatorBytes, 0, separatorBytes.Length); | |
} | |
await this.OutputStream.WriteAsync(endOfLineBytes, 0, endOfLineBytes.Length); | |
} | |
private PropertyInfo[] GetFilteredProperties(Type type) | |
{ | |
var properties = GetPropertyInfo(type); | |
properties = properties.Where(p => IgnoreProperties.Contains(p.Name) == false && p.CanRead).ToArray(); | |
return properties; | |
} | |
private static PropertyInfo[] GetPropertyInfo(Type type) | |
{ | |
if (TypeCache.ContainsKey(type)) | |
return TypeCache[type]; | |
PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); | |
TypeCache[type] = properties; | |
return properties; | |
} | |
public void Dispose() | |
{ | |
Dispose(true); | |
GC.SuppressFinalize(this); | |
} | |
protected virtual void Dispose(bool disposing) | |
{ | |
if (disposing) | |
{ | |
// free managed resources | |
//if (managedResource != null) | |
//{ | |
// managedResource.Dispose(); | |
// managedResource = null; | |
//} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment