列名称为垂直时从CSV读取值

时间:2019-12-02 11:50:21

标签: c# csv csvhelper

我有一个CSV帮助程序的实现,当前它以传统格式读取CSV:

Name, Address, Age
"Foo", "Foo's address", 24
"Bar", "Bar's address", 19

我使用类映射通过以下方式将字段按名称映射到我的Person对象:

using (var reader = new StreamReader(file, Encoding.UTF8))
{
    using (var csvReader = new CsvReader(reader))
    {
        csvReader.Configuration.RegisterClassMap<ContentMapper>();
        var records = csvReader.GetRecords<Person>().ToArray();
    }
}

我需要一个实现来读取完全相同的数据,但采用垂直格式的实现,该格式源自第一列中的列名是垂直的并且数据紧随列而不是行的数据。

Name, "Foo", "Bar"
Address, "Foo's address", "Bar's address"
Age, 24, 19

在保留原始映射的同时处理这种格式的CSV的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

尝试这个

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
    public int Age { get; set; }


    public List<Person> ReadFile(string path)
    {
        char[] charsToTrim1 = {'\\', ' ', '"', '\"'};

        var fileData = File.ReadAllLines(path);
        var outputData = new List<Person>();

        for (var i = 0; i < fileData.Length; i++)
        {
            var tmpData = fileData[i].Split(',');

            for (var j = 0; j < tmpData.Length; j++)
            {
                var t1 = tmpData[j].Trim(charsToTrim1);
                if (j == 0)
                    continue;
                switch (i)
                {
                    case 0:
                    {
                        var tmPerson = new Person {Name = t1};
                        outputData.Add(tmPerson);
                    }
                        break;
                    case 1:
                    {
                        outputData[j - 1].Address = t1;
                    }
                        break;
                    case 2:
                    {
                        outputData[j - 1].Age = Convert.ToInt32(t1);
                    }
                        break;
                }
            }
        }


        return outputData;
    }
}

答案 1 :(得分:0)

这可能需要清理一点,但似乎确实可行。

  • 使用CsvHelper以List<dynamic>的形式提取记录
  • 将记录旋转到新的List<dynamic>中,以便每行的第一个字段成为动态记录的属性名称。
  • 使用CsvHelper将新列表写入内存。
  • 使用CsvHelper通过ClassMap来读回记录
public class Program
{
    public static void Main(string[] args)
    {
        var flippedRecords = new List<dynamic>();

        using (MemoryStream stream = new MemoryStream())
        using (StreamWriter writer = new StreamWriter(stream))
        using (StreamReader reader = new StreamReader(stream))
        using (CsvReader csv = new CsvReader(reader))
        {
            writer.WriteLine("Name,Foo,Bar");
            writer.WriteLine("Address,Foo's address,\"Bar's address with, comma\"");
            writer.WriteLine("Age,24,19");
            writer.Flush();
            stream.Position = 0;

            csv.Configuration.HasHeaderRecord = false;

            // Get the records from the CSV file.
            var records = csv.GetRecords<dynamic>().ToList();

            // Rotate the records into a new dynamic list.
            var rows = new List<IDictionary<string, object>>();                

            foreach (var row in records)
            {
                rows.Add(row as IDictionary<string, object>);
            }

            for (int i = 2; i <= rows[0].Count; i++)
            {
                var flippedRecord = new ExpandoObject() as IDictionary<string, object>;

                foreach (var row in rows)
                {
                    flippedRecord.Add((string)row["Field1"], row["Field" + i]);
                }

                flippedRecords.Add(flippedRecord);
            }
        }

        using (MemoryStream stream = new MemoryStream())
        using (StreamWriter writer = new StreamWriter(stream))
        using (CsvWriter csvWriter = new CsvWriter(writer))
        using (StreamReader reader = new StreamReader(stream))
        using (CsvReader csvReader = new CsvReader(reader))
        {
            // Write the new list to memory
            csvWriter.WriteRecords(flippedRecords);
            writer.Flush();
            stream.Position = 0;

            // Read in the person records using a ClassMap.
            csvReader.Configuration.RegisterClassMap<PersonMap>();

            var people = csvReader.GetRecords<Person>().ToArray();
        }
    }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public int Age { get; set; }
}

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Map(m => m.FirstName).Name("Name");
        Map(m => m.Address);
        Map(m => m.Age);
    }
}