Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I've been doing some CSV reading and writing lately, and ran across CsvHelper which is fantastic so far. I've ran into one small problem; I use a custom converter when reading the files, but when I write them back out, that format is lost. My CSV format looks like this:

67,1234-1,20150115,750,20150115,1340,549,549,406,0,FRG

The fields 20150115,750 map to 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 great, and I can now call parse an entire file like so:

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 out like so:

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 don't see a way to specify a conversation function upon writing, only reading. The only solution I've found so far is to manually write each record by hand:

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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
1.1k views
Welcome To Ask or Share your Answers For Others

1 Answer

You can do it with a custom type converters (https://github.com/JoshClose/CsvHelper/wiki/Custom-TypeConverter). Just override ConvertToString method.

public class TestConverter : DefaultTypeConverter
{
    public override string ConvertToString(TypeConverterOptions options, object value)
    {
        return base.ConvertToString(options, value);
    }
}

and specify converter when mapping:

Map(m => m.PersonId).Index(0).TypeConverter<TestConverter>();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...