如何使用FileHelpers将csv文件中的2d数组映射到poco集合或字典字典?

时间:2015-12-02 15:54:41

标签: c# parsing mapping filehelpers

我的csv文件中有以下数据结构:

enter image description here

我想要将其解析为以下数据结构:

[DelimitedRecord(","), IgnoreFirst(1)]
public class FxConversionRate
{
    [FieldConverter(ConverterKind.Date, "d/M/yyyy")]
    public DateTime Date;
    public string Currency;
    public double Rate;
}

或者想要将其解析为Dictionary<string, Dictionary<DateTime, double>>

我怎样才能完成任何一种方式?我不想修改源csv表布局,并认为我需要自定义导入和映射。

由于

修改

以下代码片段,将数据从csv读取到2D数组中,也读取到数据结构(本例中的字典词典,但也可以是上面提出的数据结构FxConversionRate):

public class FxConversionTable
{
    public Dictionary<Currency, Dictionary<DateTime, double>> FxConversionRates{ get; set; } //key1 = Currency, key2 = DateTime, value = double
    public string[,] String2DArray{ get; set; }

    public FxConversionTable()
    {
        FxConversionRates = new Dictionary<Currency, Dictionary<DateTime, double>>();
    }

    public void ReadFxConversionRatesFromCsvFile(string pathFileName)
    {
        var strings = new List<List<string>>();

        using (var reader = new StreamReader(File.OpenRead(pathFileName)))
        {
            //read symbol rows and parse
            while (!reader.EndOfStream)
            {
                var line = reader.ReadLine();

                if (string.IsNullOrEmpty(line))
                    continue;

                var values = line.Split(',');

                //populate string array
                strings.Add(values.ToList());

                //header
                if (strings.Count == 1)
                {
                    foreach (var currencyString in values.Skip(1))
                    {
                        Currency ccy = (Currency) Enum.Parse(typeof (Currency), currencyString);
                        FxConversionRates.Add(ccy, new Dictionary<DateTime, double>());
                    }

                    continue;
                }

                //populate data collection
                var date = DateTime.ParseExact(values[0], "d/M/yyyy", CultureInfo.InvariantCulture);

                for (int i = 1; i < values.Count(); i++)
                {
                    var ccy = (Currency) Enum.Parse(typeof (Currency), strings[0][i]);
                    FxConversionRates[ccy].Add(date, Convert.ToDouble(values[i]));
                }
            }
        }

        String2DArray = FileIO.ListOfListTo2DArray<string>(strings);
    }
}

然而,我仍在寻找通过FileHelpers提供更通用的解决方案......

1 个答案:

答案 0 :(得分:1)

这应该可以帮到你。它不是最优雅的解决方案,但它有效。您需要为丢失列或数据或源文件损坏等内容添加大量错误检查。

    private static void Main(string[] args)
    {
        var fileData = File.ReadAllBytes("Data.csv");
        var tableData = CreateDataTableFromFile(fileData);

        DataColumn dateColumn = tableData.Columns["Date"];
        Dictionary<string, List<FxConversionRate>> rates = new Dictionary<string, List<FxConversionRate>>();
        foreach (DataColumn column in tableData.Columns)
        {
            if (column != dateColumn)
            {
                foreach (DataRow row in tableData.Rows)
                {
                    FxConversionRate rate = new FxConversionRate();
                    rate.Currency = column.ColumnName;
                    rate.Date = DateTime.Parse(row[dateColumn].ToString());
                    rate.Rate = double.Parse(row[column].ToString());
                    if (!rates.ContainsKey(column.ColumnName))
                        rates.Add(column.ColumnName, new List<FxConversionRate>());
                    rates[column.ColumnName].Add(rate);
                }
            }
        }

        foreach (var key in rates.Keys)
        {
            Console.WriteLine($"Found currency: {key}");
            foreach (var rate in rates[key])
            {
                Console.WriteLine($"   {rate.Date.ToShortDateString()} : {rate.Rate:###,###,##0.00}");
            }
        }

        Console.WriteLine("Press any key");
        Console.ReadKey();
    }

    private static DataTable CreateDataTableFromFile(byte[] importFile)
    {
        var cb = new DelimitedClassBuilder("temp", ",") { IgnoreFirstLines = 0, IgnoreEmptyLines = true, Delimiter = "," };
        var ms = new MemoryStream(importFile);
        var sr = new StreamReader(ms);
        var headerArray = sr.ReadLine().Split(',');
        foreach (var header in headerArray)
        {
            cb.AddField(header, typeof(string));
            cb.LastField.FieldQuoted = true;
            cb.LastField.QuoteChar = '"';
        }
        var engine = new FileHelperEngine(cb.CreateRecordClass());
        return engine.ReadStreamAsDT(sr);
    }

请注意,CreateDataTableFromFile例程取自https://stackoverflow.com/a/6045923/697159