Recently, I have been reading and writing CSV and have come across CsvHelper , which is still fantastic. I ran into one small problem; I use a custom converter when reading files, but when I unsubscribe, this format is lost. My CSV format is as follows:
67,1234-1,20150115,750,20150115,1340,549,549,406,0,FRG
Fields 20150115,750 displayed in a single DateTime field called Start (So, 01/15/2015 7:50 AM). My class map looks like this:
public sealed class DutyMap : CsvClassMap<Duty> { static readonly CultureInfo enUS = new CultureInfo("en-US"); public DutyMap() { Map(m => m.PersonId).Index(0); Map(m => m.DutyName).Index(1); Map(m => m.Start).ConvertUsing(row => ParseDate(row.GetField<String>(2), row.GetField<String>(3))); Map(m => m.End).ConvertUsing(row => ParseDate(row.GetField<String>(4), row.GetField<String>(5))); Map(m => m.DutyTime1).Index(6); Map(m => m.DutyTime2).Index(7); Map(m => m.FlightTime).Index(8); Map(m => m.CreditHours).Index(9); Map(m => m.DutyType).Index(10); } private static DateTime ParseDate(string date, string time) { DateTime ret; if (time.Length < 4) time = new String('0', 4 - time.Length) + time; if (!DateTime.TryParseExact(date + time, "yyyyMMddHHmm", enUS, DateTimeStyles.None, out ret)) throw new FormatException(String.Format("Could not parse DateTime. Date: {0} Time: {1}", date, time)); return ret; } }
This works fine, and now I can call the whole file parsing:
var csv = new CsvReader(sr); csv.Configuration.HasHeaderRecord = false; csv.Configuration.RegisterClassMap<DutyMap>(); Data = csv.GetRecords<Duty>().ToList();
However, when I write the file:
csv.WriteRecords(Data);
The file is written like this:
67,7454-1,1/15/2015 7:50:00 AM,1/15/2015 1:40:00 PM,549,549,406,0,FPG
Looking through the documentation, I see no way to specify the conversation function when recording, read only. The only solution I have found so far is to manually record each entry manually:
var csv = new CsvWriter(sw); foreach (var item in Data) { csv.WriteField(item.PersonId); csv.WriteField(item.DutyName); csv.WriteField(item.Start.ToString("yyyyMMdd")); csv.WriteField(item.Start.ToString("Hmm")); csv.WriteField(item.End.ToString("yyyyMMdd")); csv.WriteField(item.End.ToString("Hmm")); csv.WriteField(item.DutyTime1); csv.WriteField(item.DutyTime2); csv.WriteField(item.FlightTime); csv.WriteField(item.CreditHours); csv.WriteField(item.DutyType); csv.NextRecord(); }
Is there a better way to do this? Thanks!