C# CSV Reader with Linq

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;


using LumenWorks.Framework.IO.Csv;


public class CsvQueryReader<TEntry> : IDisposable where TEntry : struct
{
    private CsvReader m_csvReader;
    private FieldTypeInfo[] m_fieldTypeInfos;


    private bool m_isDisposed = false;


    public CsvQueryReader(string path, Encoding encoding, Boolean hasHeader)
    {
        m_csvReader = new CsvReader(new StreamReader(path, encoding), hasHeader);
        Initialize();
    }


    public CsvQueryReader(Stream stream, Encoding encoding, Boolean hasHeader)
    {
        m_csvReader = new CsvReader(new StreamReader(stream, encoding), hasHeader);
        Initialize();
    }


    ~CsvQueryReader()
    {
        Dispose(false);
    }


    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }


    protected virtual void Dispose(bool disposing)
    {
        if (!m_isDisposed)
        {
            if (disposing)
            {
                if (m_csvReader != null)
                    m_csvReader.Dispose();
            }
        }


        m_isDisposed = true;
    }


    public IEnumerable<TEntry> ReadAllEntries()
    {
        TEntry? entry;
        while ((entry = ReadEntry()).HasValue)
            yield return entry.Value;
    }


    public IEnumerable<TEntry> ReadAllEntries(Int32 startField, Int32 endField)
    {
        TEntry? entry;
        while ((entry = ReadEntry(startField, endField)).HasValue)
            yield return entry.Value;
    }


    // Nullable reurn type
    public TEntry? ReadEntry()
    {
        if (!m_csvReader.ReadNextRecord())
            return null;


        var entry = new TEntry();
        FieldTypeInfo fieldTypeInfo;
        object fieldValue;


        for (int i = 0; i < m_csvReader.Count(); i++)
        {
            fieldTypeInfo = m_fieldTypeInfos[i];
            fieldValue = fieldTypeInfo.TypeConverter.ConvertFromString(m_csvReader[i].Trim());
            fieldTypeInfo.FieldInfo.SetValueDirect(__makeref(entry), fieldValue);
        }


        return entry;
    }


    // Nullable reurn type
    public TEntry? ReadEntry(Int32 startField, Int32 endField)
    {
        if (!m_csvReader.ReadNextRecord())
            return null;


        var entry = new TEntry();
        FieldTypeInfo fieldTypeInfo;
        object fieldValue;


        int j = 0;
        for (int i = startField; i <= endField; i++)
        {
            fieldTypeInfo = m_fieldTypeInfos[j++];
            fieldValue = fieldTypeInfo.TypeConverter.ConvertFromString(m_csvReader[i].Trim());
            fieldTypeInfo.FieldInfo.SetValueDirect(__makeref(entry), fieldValue);
        }


        return entry;
    }


    private void Initialize()
    {
        var entryType = typeof(TEntry);
        m_fieldTypeInfos = (from fieldInfo in entryType.GetFields(BindingFlags.Instance |
                              BindingFlags.Public)
                          let fieldTypeConverterAttrib = fieldInfo.GetCustomAttributes(
                              typeof(TypeConverterAttribute), true).SingleOrDefault()
                              as TypeConverterAttribute
                          let fieldTypeConverter = (fieldTypeConverterAttrib == null) ? null :
                              Activator.CreateInstance(Type.GetType(
                                  fieldTypeConverterAttrib.ConverterTypeName))
                              as TypeConverter
                          select new FieldTypeInfo()
                          {
                              FieldInfo = fieldInfo,
                              TypeConverter = fieldTypeConverter ??
                                  TypeDescriptor.GetConverter(fieldInfo.FieldType)
                          }).ToArray();
    }


    private struct FieldTypeInfo
    {
        public FieldInfo FieldInfo;
        public TypeConverter TypeConverter;
    }
}

댓글

이 블로그의 인기 게시물

Publish to my blog (weekly)

Publish to my blog (weekly)