Используя CsvHelper я могу перевести пустое пространство в обнуляемое значение?

У меня есть некоторые действительно хромые файлы CSV, которые мне нужно проанализировать. Я использую CsvHelper, и он работает потрясающе. За исключением того, что у меня есть несколько строк, которые имеют пробелы, где обычно у меня есть двойной.

Файл:

Текст, SomeDouble, MoreText

«Хорошо», 1,23, «Хорошо»

«Плохо», «Плохо»

если я попытаюсь отобразить это в

public class Test
{
  [CsvField(Name = "Text")]
  public string Text { get; set; }

  [CsvField(Name = "SomeDouble")]
  public double? SomeDouble{ get; set; }

  [CsvField(Name = "MoreText")]
  public string MoreText{ get; set; }
}

тогда я получаю ошибку как это:

CsvHelper.CsvReaderException: произошла ошибка при попытке прочитать запись типа

Строка: '2' (на основе 1)

Индекс поля: '1' (на основе 0)

Имя поля: SomeDouble

Значение поля: ''

System.Exception: недопустимое значение для Double. ---> System.FormatException: входная строка была в неправильном формате.
в System.Number.ParseDouble (строковое значение, параметры NumberStyles, NumberFormatInfo numfmt) в System.ComponentModel.DoubleConverter.FromString (строковое значение, NumberFormatInfo formatInfo) в System.ComponentModel.BaseNumberConverter.ConvertFrom (value) context, culturetexture (ITypeDescript) - Конец внутренней трассировки стека исключений --- в System.ComponentModel.BaseNumberConverter.ConvertFrom (контекст ITypeDescriptorContext, CultureInfo culture, значение объекта) в System.ComponentModel.NullableConverter.ConvertFrom (контекст ITypeDescriptorContext, CultureInfo culture, значение объекта at ld) Закрытие, ICsvReader) в CsvHelper.CsvReader.d__0`1.MoveNext ()

На мой взгляд, я могу создать собственный синтаксический анализатор или сопоставить мое значение со строковым свойством и выполнить там разбор.

Есть ли другие варианты?

Было бы неплохо, если бы я мог настроить, что я хочу рассматривать пустое пространство как ноль.

В соответствии с запросом приведен пример кода, который воспроизводит проблему

 static class Program
    {
        public class Test
        {
            [CsvField(Name = "Text")]
            public string Text { get; set; }

            [CsvField(Name = "SomeDouble")]
            public double? SomeDouble { get; set; }

            [CsvField(Name = "MoreText")]
            public string MoreText { get; set; }
        }

        static void Main(string[] args)
        {
            // create fake in memory file
            var memoryStream = new MemoryStream();
            var streamWriter = new StreamWriter(memoryStream);
            streamWriter.WriteLine("Text,SomeDouble,MoreText");
            streamWriter.WriteLine("Good, 1.23, Good");
            streamWriter.WriteLine("Bad, ,Bad");

            streamWriter.Flush();

            //reset the file to the begining
            memoryStream.Position = 0;

            using (
                var csv =
                    new CsvReader(
                        new StreamReader(memoryStream)))
            {
                // this call will blow up with the exception.
                var records = csv.GetRecords<Test>().ToList();

                //carry on and do stuff with 'records'...
            }
    }

Благодарю.

 Tejas Sharma25 окт. 2012 г., 01:52
Можете ли вы опубликовать код для метода, который на самом деле не работает, я не знаком с CSVHelper.
 Levin Magruder25 окт. 2012 г., 20:39
Я не думаю, что из пакета это делает, но помогает ли это:пользовательский преобразователь типа Я собираюсь посмотреть, смогу ли я получить что-нибудь с этим, я мог бы также использовать эту функцию. Пожалуйста, напишите, если вы найдете решение.
 RMK25 окт. 2012 г., 16:11
Я отредактировал вопрос с лучшим примером

Ответы на вопрос(2)

Решение Вопроса

я создал собственный конвертер типов, который будет обрабатывать пробелы так же, как и ноль.

public class WhiteSpaceToNullableTypeConverter<T> : TypeConverter where T : struct
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof (string);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof (T?);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture,
                                       object value)
    {
        T? result = null;

        var stringValue = (string) value;
        if (!string.IsNullOrWhiteSpace(stringValue))
        {
            var converter = TypeDescriptor.GetConverter(typeof(T));
            result = (T)converter.ConvertFrom(stringValue.Trim());
        }

        return result;
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture,
                                     object value, Type destinationType)
    {
        var result = (T?) value;
        return result.ToString();
    }
}

Примените это к вашей модели, как это

public class Test
{
    [CsvField(Name = "Text")]
    public string Text { get; set; }

    [CsvField(Name = "SomeDouble")]
    [TypeConverter( typeof( WhiteSpaceToNullableTypeConverter<Double> ) )]
    public double? SomeDouble{ get; set; }

    [CsvField(Name = "MoreText")]
    public string MoreText{ get; set; }
}

Map(x => x.SomeDouble)
    .ConvertUsing(row => 
        string.IsNullOrWhiteSpace(row.GetField("SomeDouble")) ?
            (double?) null : 
            Convert.ToDouble(row.GetField("SomeDouble")));

Мне нравится делать маленькие вспомогательные функции и вызывать их

Map(x => x.SomeDouble)
    .ConvertUsing(row => GetOddballDouble(row.GetField("SomeDouble")));

Ваш ответ на вопрос