Skip to content

Instantly share code, notes, and snippets.

@RhysC
Created March 15, 2013 09:50
Show Gist options
  • Save RhysC/5168701 to your computer and use it in GitHub Desktop.
Save RhysC/5168701 to your computer and use it in GitHub Desktop.
CSV reader from http://www.thinqlinq.com/default/LINQ-to-CSV-using-DynamicObject.aspx. Ported to c# with basic usage example at the bottom (using xunit). Uses dynamic to provide the field names based on headers. Have changed the default of changing spaces to underscores to just removing them.
using System;
using System.Dynamic;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using Xunit;
namespace YourNamespace
{
public class DynamicCsv : DynamicObject
{
private readonly Dictionary<string, int> _fieldIndex;
private readonly string[] _rowValues;
internal DynamicCsv(string currentRow, Dictionary<string, int> fieldIndex)
{
_rowValues = currentRow.Split(',');
_fieldIndex = fieldIndex;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_fieldIndex.ContainsKey(binder.Name))
{
result = _rowValues[_fieldIndex[binder.Name]];
return true;
}
result = null;
return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (_fieldIndex.ContainsKey(binder.Name))
{
_rowValues[_fieldIndex[binder.Name]] = value.ToString();
return true;
}
return false;
}
}
public class DynamicCsvEnumerator : IEnumerator<object>, IEnumerable<object>
{
private TextReader _fileStream;
private Dictionary<string, int> _fieldNames;
private DynamicCsv _currentRow;
private readonly string _filename;
public DynamicCsvEnumerator(string fileName)
{
_filename = fileName;
}
IEnumerator<object> IEnumerable<object>.GetEnumerator()
{
_fileStream = new StreamReader(_filename);
var headerRow = _fileStream.ReadLine();
if (string.IsNullOrWhiteSpace(headerRow))
throw new InvalidOperationException("Header row must have values");
var fields = headerRow.Split(',');
_fieldNames = new Dictionary<string, int>();
for (var i = 0; i <= fields.Length - 1; i++)
{
_fieldNames.Add(GetSafeFieldName(fields[i]), i);
}
return this;
}
public string GetSafeFieldName(string input)
{
return input.Replace(" ", "");
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<object>)this).GetEnumerator();
}
object IEnumerator<object>.Current
{
get { return _currentRow; }
}
object IEnumerator.Current
{
get
{
return ((IEnumerator<object>)this).Current;
}
}
bool IEnumerator.MoveNext()
{
var line = _fileStream.ReadLine();
if (!string.IsNullOrEmpty(line))
{
_currentRow = new DynamicCsv(line, _fieldNames);
return true;
}
return false;
}
void IEnumerator.Reset()
{
_fileStream.Close();
// ReSharper disable ReturnValueOfPureMethodIsNotUsed
((IEnumerable<object>)this).GetEnumerator();//Reopens stream
// ReSharper restore ReturnValueOfPureMethodIsNotUsed
}
public void Dispose()
{
_fileStream.Dispose();
}
}
public class CsvTester
{
[Fact]
public void doesCsvWork()
{
var data = new DynamicCsvEnumerator(@"C:\FileWithNames.csv");
foreach (dynamic item in data)
{
Console.WriteLine(item.title + ": " +
item.firstName + ": " +
item.middleName + ": " +
item.lastName);
}
}
}
}
@jkaleta
Copy link

jkaleta commented Apr 9, 2014

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment