使用 ClassMap 的 CsvHelper 格式十进制
CsvHelper Format Decimal using ClassMap
我在文件中有一些列,这些列的值类似于“000120000”,需要使用 CsvHelper ClassMap 将其转换为“1200.00”。我目前正在为这些列使用 Decimal 类型,并在 ClassMap 中使用 NumberStyle 来截断开头的零。所以我得到的值为“120000”。我尝试使用 "TypeConverterOption.Format("0.00")" 但没有成功。所以想知道是否有一种方法可以使用 ClassMap 将值“120000”转换为“1200.00”。我什至可以除以 100,但不想在我使用该字段的任何地方都这样做,因此需要在 ClassMap 中执行此逻辑。预先感谢您帮助我解决这个问题。
在 ClassMap 中我有以下代码:
csvConfig.TypeConverterOptionsCache.GetOptions<小数?>().NumberStyle =
NumberStyles.Number | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent;
例如:“000120000”->“1200.00”(现在我得到的值为“120000”)
这是您可以做到的一种方式。使用自定义转换器。
public class Program
{
static void Main(string[] args)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("Id,MoveDecimalPoint,NoMoveDecimalPoint");
writer.WriteLine("1,000120000,000120000");
writer.Flush();
stream.Position = 0;
csv.Configuration.RegisterClassMap<FooClassMap>();
var records = csv.GetRecords<Foo>().ToList();
}
}
}
public class Foo
{
public int Id { get; set; }
public decimal MoveDecimalPoint { get; set; }
public decimal NoMoveDecimalPoint { get; set; }
}
public class FooClassMap : ClassMap<Foo>
{
public FooClassMap()
{
AutoMap(CultureInfo.InvariantCulture);
Map(m => m.MoveDecimalPoint).TypeConverter<MoveDecimalConverter>();
}
}
public class MoveDecimalConverter : DecimalConverter
{
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
var numberStyle = memberMapData.TypeConverterOptions.NumberStyle ?? NumberStyles.Number;
if (decimal.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var d))
{
return d / 100;
}
return base.ConvertFromString(text, row, memberMapData);
}
}
如果你想让所有的十进制值都移动两位小数,你可以在配置中添加 MoveDecimalConverter
。
public class Program
{
static void Main(string[] args)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("Id,MoveDecimalPoint,NoMoveDecimalPoint");
writer.WriteLine("1,000120000,000120000");
writer.Flush();
stream.Position = 0;
csv.Configuration.TypeConverterCache.AddConverter<decimal>(new MoveDecimalConverter());
var records = csv.GetRecords<Foo>().ToList();
}
}
}
您也可以使用 ConvertUsing()
public class Program
{
static void Main(string[] args)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("Id,MoveDecimalPoint,NoMoveDecimalPoint");
writer.WriteLine("1,000120000,000120000");
writer.Flush();
stream.Position = 0;
csv.Configuration.RegisterClassMap<FooClassMap>();
var records = csv.GetRecords<Foo>().ToList();
}
}
}
public class Foo
{
public int Id { get; set; }
public decimal MoveDecimalPoint { get; set; }
public decimal NoMoveDecimalPoint { get; set; }
}
public class FooClassMap : ClassMap<Foo>
{
public FooClassMap()
{
AutoMap(CultureInfo.InvariantCulture);
Map(m => m.MoveDecimalPoint).ConvertUsing(row =>
{
if (decimal.TryParse(row["MoveDecimalPoint"], NumberStyles.Number, row.Configuration.CultureInfo, out var d))
{
return d / 100;
}
else
{
return 0;
}
});
}
}
我在文件中有一些列,这些列的值类似于“000120000”,需要使用 CsvHelper ClassMap 将其转换为“1200.00”。我目前正在为这些列使用 Decimal 类型,并在 ClassMap 中使用 NumberStyle 来截断开头的零。所以我得到的值为“120000”。我尝试使用 "TypeConverterOption.Format("0.00")" 但没有成功。所以想知道是否有一种方法可以使用 ClassMap 将值“120000”转换为“1200.00”。我什至可以除以 100,但不想在我使用该字段的任何地方都这样做,因此需要在 ClassMap 中执行此逻辑。预先感谢您帮助我解决这个问题。
在 ClassMap 中我有以下代码: csvConfig.TypeConverterOptionsCache.GetOptions<小数?>().NumberStyle = NumberStyles.Number | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent;
例如:“000120000”->“1200.00”(现在我得到的值为“120000”)
这是您可以做到的一种方式。使用自定义转换器。
public class Program
{
static void Main(string[] args)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("Id,MoveDecimalPoint,NoMoveDecimalPoint");
writer.WriteLine("1,000120000,000120000");
writer.Flush();
stream.Position = 0;
csv.Configuration.RegisterClassMap<FooClassMap>();
var records = csv.GetRecords<Foo>().ToList();
}
}
}
public class Foo
{
public int Id { get; set; }
public decimal MoveDecimalPoint { get; set; }
public decimal NoMoveDecimalPoint { get; set; }
}
public class FooClassMap : ClassMap<Foo>
{
public FooClassMap()
{
AutoMap(CultureInfo.InvariantCulture);
Map(m => m.MoveDecimalPoint).TypeConverter<MoveDecimalConverter>();
}
}
public class MoveDecimalConverter : DecimalConverter
{
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
var numberStyle = memberMapData.TypeConverterOptions.NumberStyle ?? NumberStyles.Number;
if (decimal.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var d))
{
return d / 100;
}
return base.ConvertFromString(text, row, memberMapData);
}
}
如果你想让所有的十进制值都移动两位小数,你可以在配置中添加 MoveDecimalConverter
。
public class Program
{
static void Main(string[] args)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("Id,MoveDecimalPoint,NoMoveDecimalPoint");
writer.WriteLine("1,000120000,000120000");
writer.Flush();
stream.Position = 0;
csv.Configuration.TypeConverterCache.AddConverter<decimal>(new MoveDecimalConverter());
var records = csv.GetRecords<Foo>().ToList();
}
}
}
您也可以使用 ConvertUsing()
public class Program
{
static void Main(string[] args)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("Id,MoveDecimalPoint,NoMoveDecimalPoint");
writer.WriteLine("1,000120000,000120000");
writer.Flush();
stream.Position = 0;
csv.Configuration.RegisterClassMap<FooClassMap>();
var records = csv.GetRecords<Foo>().ToList();
}
}
}
public class Foo
{
public int Id { get; set; }
public decimal MoveDecimalPoint { get; set; }
public decimal NoMoveDecimalPoint { get; set; }
}
public class FooClassMap : ClassMap<Foo>
{
public FooClassMap()
{
AutoMap(CultureInfo.InvariantCulture);
Map(m => m.MoveDecimalPoint).ConvertUsing(row =>
{
if (decimal.TryParse(row["MoveDecimalPoint"], NumberStyles.Number, row.Configuration.CultureInfo, out var d))
{
return d / 100;
}
else
{
return 0;
}
});
}
}