Использование csvHelper для чтения содержимого ячейки в список или массив

У меня есть файл csv типа:

name,numbersA,numbersB
Bob,"1,2,3,4","6,7,8,9"
Brabra,"9,3","4,8,5,7,2"

Таким образом, массивы int задаются числами между "".

Я хочу сопоставить это со следующим классом

    public class Names
    {
        [Name("name")]
        public string Name { get; set; }

        [Name("numbersA")]
        public List<int> NumbersA{ get; set; }

        [Name("numbersB")]
        public List<int> NumbersB{ get; set; }

    }

Я не особо возражаю, если NumbersA / B имеет тип int [] или List. Пока мне удалось прочитать данные, указав тип NumbersA / B как строку, и это работает правильно (я получаю строку между ""). Может ли это быть сделано автоматически в csvHelper или мне нужно будет сам разбирать строку позже.

void Main()
{
    using (var reader = new StreamReader("path\\to\\file.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var records = csv.GetRecords<Names>();
        List<Names> NameList = records.ToList();
    }
}

Любая помощь будет очень высоко ценится.

РЕШЕНИЕ

Благодарим @Oguz Ozgul (см. Ниже). Внес пару незначительных изменений.


public class Names
{
    [Name("name")]
    public string Name { get; set; }

    [Name("numbersA")]
    [TypeConverter(typeof(ToIntArrayConverter))]
    public List<int> NumbersA{ get; set; }

    [Name("numbersB")]
    [TypeConverter(typeof(ToIntArrayConverter))]
    public List<int> NumbersB{ get; set; }

}

public class ToIntArrayConverter : TypeConverter
{
    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        if (text == "") return new List<int>();
        string[] allElements = text.Split(',');
        int[] elementsAsInteger = allElements.Select(s => int.Parse(s)).ToArray();
        return new List<int>(elementsAsInteger);
    }

    public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
    {
        return string.Join(",", ((List<int>)value).ToArray());
    }
}


person Eule    schedule 01.04.2020    source источник


Ответы (1)


Вы можете реализовать преобразователь настраиваемого типа и использовать его во время преобразования (в обоих направлениях) для ваших двух свойств.

Класс TypeConverter находится в пространстве имен CsvHelper.TypeConversion

TypeConverterAttribute находится в пространстве имен CsvHelper.Configuration.Attributes

    public class ToIntArrayConverter : TypeConverter
    {
        public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
        {
            string[] allElements = text.Split(',');
            int[] elementsAsInteger = allElements.Select(s => int.Parse(s)).ToArray();
            return new List<int>(elementsAsInteger);
        }

        public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
        {
            return string.Join(',', ((List<int>)value).ToArray());
        }
    }

Чтобы использовать этот конвертер, просто добавьте следующие TypeConverterAttribute аннотации поверх своих свойств:

    public class Names
    {
        [Name("name")]
        public string Name { get; set; }

        [Name("numbersA")]
        [TypeConverter(typeof(ToIntArrayConverter))]
        public List<int> NumbersA { get; set; }

        [Name("numbersB")]
        [TypeConverter(typeof(ToIntArrayConverter))]
        public List<int> NumbersB { get; set; }
    }
person Oguz Ozgul    schedule 01.04.2020
comment
Готово, извините, я новичок в этом :) - person Eule; 01.04.2020
comment
Я получаю Cannot Resolve Symbol ToIntArrayConverter Я использую этот импорт: using CsvHelper.Configuration.Attributes; using CsvHelper.TypeConversion; using CsvHelper; - person tblev; 28.04.2021
comment
Привет @tblev в ответе реализован класс ToIntArrayConverter. Вам нужно скопировать класс сверху. - person Oguz Ozgul; 07.05.2021