【问题标题】:CsvHelper Parsing boolean from StringCsvHelper 从字符串解析布尔值
【发布时间】:2017-10-27 08:29:45
【问题描述】:

我目前正在尝试从一个布尔值的 csv 文件中解析一个值。我们注意到该值将成功解析 YesY(在任何情况下),但不会解析 NoN

我正在像这样映射类映射中的值:

Map(m => m.Enabled).Name("Enabled").TypeConverterOption(false, string.Empty);

这有什么原因会显示为Yes 而不是No,有没有办法添加解析no 的功能?

【问题讨论】:

标签: c# csv csvhelper


【解决方案1】:

作为一种扩展方法,使使用更简单。

Map(x => x.IsActive).Name("Active").WithExtendedBooleanValues();

在 v15 上测试,但我确信在那之前它运行良好。

namespace CsvHelper.Configuration
{
    public static class MemberMapExtensions
    {
        /// <summary>
        /// Adds "y", "yes" and "set to yes" and the "no" equivalents to the list of accepted boolean values
        /// for this member map.
        /// </summary>
        public static MemberMap<TClass, TMember> WithExtendedBooleanValues<TClass, TMember>(
            this MemberMap<TClass, TMember> memberMap)
        {
            memberMap
                // Note: It's case insensitive
                // https://github.com/JoshClose/CsvHelper/blob/master/src/CsvHelper/TypeConversion/BooleanConverter.cs
                .TypeConverterOption.BooleanValues(true, clearValues: false, "y", "yes", "set to yes")
                .TypeConverterOption.BooleanValues(false, clearValues: false, "n", "no", "set to no");

            return memberMap;
        }
    }
}

【讨论】:

  • 这是我在任何地方找到的唯一可行的解​​决方案。
【解决方案2】:

在 4.0.3 版本中,这可以工作。

void Main()
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    using (var reader = new StreamReader(stream))
    using (var csv = new CsvReader(reader))
    {
        writer.WriteLine("Id,Name,IsSomething");
        writer.WriteLine("1,one,Yes");
        writer.WriteLine("2,two,Y");
        writer.WriteLine("3,three,No");
        writer.WriteLine("4,four,N");
        writer.Flush();
        stream.Position = 0;

        csv.Configuration.RegisterClassMap<TestMap>();
        csv.GetRecords<Test>().ToList().Dump();
    }
}

public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsSomething { get; set; }
}

public sealed class TestMap : ClassMap<Test>
{
    public TestMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
        Map(m => m.IsSomething)
            .TypeConverterOption.BooleanValues(true, true, "Yes", "Y")
            .TypeConverterOption.BooleanValues(false, true, "No", "N");
    }
}

在 2.16.3 版本中可以使用。

void Main()
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    using (var reader = new StreamReader(stream))
    using (var csv = new CsvReader(reader))
    {
        writer.WriteLine("Id,Name,IsSomething");
        writer.WriteLine("1,one,Yes");
        writer.WriteLine("2,two,Y");
        writer.WriteLine("3,three,No");
        writer.WriteLine("4,four,N");
        writer.Flush();
        stream.Position = 0;

        csv.Configuration.RegisterClassMap<TestMap>();
        csv.GetRecords<Test>().ToList().Dump();
    }
}

public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsSomething { get; set; }
}

public sealed class TestMap : CsvClassMap<Test>
{
    public TestMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
        Map(m => m.IsSomething)
            .TypeConverterOption(true, "Yes", "Y")
            .TypeConverterOption(false, "No", "N");
    }
}

【讨论】:

  • 在 4.0.3 版本中,我想知道为什么我们必须添加两个“true”而不是一个。
【解决方案3】:

我们在版本 7 中使用以下内容

用于单个映射:

Map(m => m.IsSomething).Name("IsSomething").TypeConverter<MyBooleanConverter>();

适用于 CSV 阅读器的用法

csv.Configuration.TypeConverterCache.AddConverter<bool>(new MyBooleanConverter());

代码:

public sealed class MyBooleanConverter : DefaultTypeConverter
{
    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        if(TryParseConvertBoolean(text, out bool result))
        {
            return result;
        }

        return null;
    }

    public static bool TryParseConvertBoolean(string value, out bool result)
    {
        result = false;
        try
        {
            if (string.IsNullOrWhiteSpace(value))
                return false;
            else
            {
                var lower = value.ToLower();

                if (lower == "no" || lower == "n")
                {
                    result = false;
                    return true;
                }
                else if (lower == "yes" || lower == "y")
                {
                    result = true;
                    return true;
                }
            }
        }
        catch { }

        return false;
    }
}

【讨论】:

    猜你喜欢
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 2013-08-22
    • 2011-06-14
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    相关资源
    最近更新 更多