CsvHelper - Read different record types in same CSV

前端 未结 2 1464
忘了有多久
忘了有多久 2021-01-27 13:46

I\'m trying to read two types of records out of a CSV file with the following structure:

PlaceName,Longitude,Latitude,El         


        
相关标签:
2条回答
  • 2021-01-27 14:38

    I got a response from Josh Close on the issue tracker:

    CsvReader not recognising different registered class maps

    Here is his answer to this question:

    Since you don't have a single header, you'll need to ignore headers and use indexes instead. This brings up an idea though. I could have the ReadHeader method parse headers for a specific record type.

    Here is an example that should work for you though.

    void Main()
    {
        LocationDefinition Location;
        var Counts = new List<CountDefinition>();
    
        using (var stream = new MemoryStream())
        using (var reader = new StreamReader(stream))
        using (var writer = new StreamWriter(stream))
        using (var csvReader = new CsvReader(reader))
        {
            writer.WriteLine("PlaceName,Longitude,Latitude,Elevation");
            writer.WriteLine("NameString,123.456,56.78,40");
            writer.WriteLine();
            writer.WriteLine("Date,Count");
            writer.WriteLine("1/1/2012,1");
            writer.WriteLine("2/1/2012,3");
            writer.WriteLine("3/1/2012,10");
            writer.WriteLine("4/2/2012,6");
            writer.Flush();
            stream.Position = 0;
    
            csvReader.Configuration.HasHeaderRecord = false;
            csvReader.Configuration.RegisterClassMap<LocationMap>();
            csvReader.Configuration.RegisterClassMap<CountMap>();
    
            csvReader.Read(); // get header
            csvReader.Read(); // get first record
            var locationData = csvReader.GetRecord<LocationDefinition>();
    
            csvReader.Read(); // skip blank line
            csvReader.Read(); // skip second header section
    
            // Read count data records
            while (csvReader.Read())
            {
                var tempCount = csvReader.GetRecord<CountDefinition>();         
                Counts.Add(tempCount);
            }
        }
    }
    
    public class LocationDefinition
    {
        public string PlaceName { get; set; }
        public double Longitude { get; set; }
        public double Latitude { get; set; }
        public double Elevation { get; set; }
    }
    
    public sealed class LocationMap : CsvClassMap<LocationDefinition>
    {
        public LocationMap()
        {
            Map(m => m.PlaceName);
            Map(m => m.Longitude);
            Map(m => m.Latitude);
            Map(m => m.Elevation);
        }
    }
    
    public class CountDefinition
    {
        public DateTime Date { get; set; }
        public int Count { get; set; }
    }
    
    public sealed class CountMap : CsvClassMap<CountDefinition>
    {
        public CountMap()
        {
            Map(m => m.Date);
            Map(m => m.Count);
        }
    }
    
    0 讨论(0)
  • 2021-01-27 14:39

    Try this

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    
    namespace ConsoleApplication1
    {
        enum State
        {
            FIND_RECORD,
            GET_LOCATION,
            GET_DATES
        }
        class Program
        {
            const string FILENAME = @"c:\temp\test.txt";
            static void Main(string[] args)
            {
                StreamReader reader = new StreamReader(FILENAME);
                State state = State.FIND_RECORD;
    
                LocationDefinition location = null;
                string inputLine = "";
                while ((inputLine = reader.ReadLine()) != null)
                {
                    inputLine = inputLine.Trim();
                    if (inputLine.Length == 0)
                    {
                        state = State.FIND_RECORD;
                    }
                    else
                    {
                        switch (state)
                        {
                            case State.FIND_RECORD :
                                if (inputLine.StartsWith("PlaceName"))
                                {
                                    state = State.GET_LOCATION;
                                }
                                else
                                {
                                    if (inputLine.StartsWith("Date"))
                                    {
                                        state = State.GET_DATES;
                                    }
                                }
                                break;
                            case State.GET_DATES :
                                if (location.dates == null) location.dates = new CountDefinition();
                                location.dates.dates.Add(new CountDefinition(inputLine));
                                break;
                            case State.GET_LOCATION :
                                location = new LocationDefinition(inputLine);
                                break;
                        }
                    }
                }
            }
        }
        public class LocationDefinition
        {
            public static List<LocationDefinition> locations = new List<LocationDefinition>();
            public CountDefinition dates { get; set; }
            public string PlaceName { get; set; }
            public double Longitude { get; set; }
            public double Latitude { get; set; }
            public double Elevation { get; set; }
    
            public LocationDefinition(string location)
            {
                string[] array = location.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                PlaceName = array[0];
                Longitude = double.Parse(array[1]);
                Latitude = double.Parse(array[2]);
                Elevation = double.Parse(array[3]);
                locations.Add(this);
             }
        }
    
    
    
        public class CountDefinition
        {
            public List<CountDefinition> dates = new List<CountDefinition>();
            public DateTime Date { get; set; }
            public int Count { get; set; }
    
            public CountDefinition() { ;}
    
            public CountDefinition(string count)
            {
                string[] array = count.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                Date = DateTime.Parse(array[0]);
                Count = int.Parse(array[1]);
                dates.Add(this);
            }
        }
    
    
    }
    
    0 讨论(0)
提交回复
热议问题