Search code examples
c#.netcsvdecimalcsvhelper

Parse csv to decimal on different cultures using CsvHelper in c#


Problem with parsing decimals by CsvHelper in c#.

I created a class that get csv file from byte[] istead of file, and it works correctly.

public static List<Topic> GetAll(byte[] attachmentBytes)
    {
        using (Stream stream = new MemoryStream(attachmentBytes))
        {
            using (var reader = new StreamReader(stream, Encoding.GetEncoding(1252), true))
            {
                using (var csv = new CsvReader(reader))
                {
                    csv.Configuration.Delimiter = ";";
                    csv.Configuration.HasHeaderRecord = true;
                    csv.Configuration.CultureInfo = CultureInfo.InvariantCulture;

                    return csv.GetRecords<Topic>().ToList();
                }
            }
        }
    }

Like you can see I added class to map csv to object:

public class Topic
{
    [Name("ID")]
    public int Id { get; set; }

    [Name("description")]
    public string Description { get; set; }

    [Name("DecimalPTS")]
    public decimal? DecimalPts { get; set; }
}

And this is how my example csv data looks like.

ID;description;DecimalPTS
1;singing;0,6
2;speaking;2,6
3;working;3,3

But this solution produces an error with

CsvHelper.TypeConversion.TypeConverterException : The conversion cannot be performed.
    Text: '0,6'
    MemberType: System.Nullable`1[[System.Decimal, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

When I replaced just do Replace(',','.'); on input, localy test pass, but on my server test fails (seems like I have different culture localy, and on the server)

What I tried to fix this issue:

  • I added csv.Configuration.CultureInfo = CultureInfo.InvariantCulture;
  • I used 7.1.1 CSV Version, but changed to 12.1.2, and still the same error

Unfortunately, nothing helped.


Solution

  • Try to set your culture to de-DE

    csv.Configuration.CultureInfo = new CultureInfo("de-DE");
    

    You can do one more trick that, if your application works on

    • local then you can set culture to en-US and if it's on a
    • server then you can set culture to de-DE.

    or vice versa.

    Demo:

    var bytes = File.ReadAllBytes(@"Path to your csv file");    
    List<Topic> list = GetAll(bytes);
    
    //Print list item to console
    foreach (var item in list)
    {
        Console.WriteLine($"ID: {item.Id}\t Description: {item.Description}\t DecimalPTS: {item.DecimalPts}");
    }
    

    Output:

    enter image description here