我有一个具有DateTime类型属性的模型。在这个属性中,我希望在写入csv文件时以及从csv文件中读取时,将秒和微秒包含在字符串中,然后使用CsvHelper。
所以我在这里是通过扩展 DefaultTypeConverter
来实现解决方案的方法public class CsvDateTimeConverter : DefaultTypeConverter
{
private const string DateStringFormat = "MM/dd/yyyy HH:mm:ss.fff";
public override object ConvertFromString(TypeConverterOptions options, string text)
{
if (string.IsNullOrEmpty(text)) return null;
return Convert.ToDateTime(text);
}
public override string ConvertToString(TypeConverterOptions options, object value)
{
if (value == null) return "";
var dateTime = (DateTime) value;
return dateTime.ToString(DateStringFormat);
}
}
模型看起来像这样
public class MyModel
{
// ..... removed other properties
public DateTime MyDateTime {get; set};
}
CsvClassMapper看起来像这样
public sealed class CsvMap : CsvClassMap<MyModel>
{
public CsvMap()
{
Map(m => m.MyDateTime).TypeConverter<CsvDateTimeConverter>();
}
}
我将班级地图注册到了读者和作家。但问题是:
我可以使用转换器成功写入csv文件,但是当我尝试从csv文件读取时,它可以读取其他属性但是为DateTime属性返回null。
那么......我错过了什么?
编辑:
如果有帮助:
这是从csv文件中读取的代码:
using (TextReader reader = new StreamReader(filePath))
{
var csv = new CsvReader(reader);
csv.Configuration.RegisterClassMap<CsvMap>();
csv.Configuration.Encoding = Encoding.UTF8;
return csv.GetRecords<MyModel>().ToList();
}
答案 0 :(得分:4)
您无需指定自定义类型转换器。这是美国式的DateTime格式,添加了毫秒数。您所需要的只是指定正确的文化,并可能指定要使用的格式。
一种选择是将Configuration.CultureInfo
属性设置为美国文化:
reader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");
以下代码将生成并读取美国日期,无毫秒:
using (var file = new StreamWriter("test.csv"))
{
var writer = new CsvWriter(file);
writer.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");
writer.WriteRecords(items);
}
using (var file = new StreamReader("test.csv"))
{
var reader= new CsvReader(file);
reader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");
var models=reader.GetRecords<MyModel>().ToArray();
Console.WriteLine(models[0]);
}
您可以通过类地图中的TypeConverterOptions
方法为字段指定不同的格式:
public sealed class CsvMap : CsvHelper.Configuration.CsvClassMap<MyModel>
{
public CsvMap()
{
Map(m => m.Date).TypeConverterOption("MM/dd/yyyy HH:mm:ss.fff");
Map(m => m.ID);
}
}
以下代码只添加了类映射,将生成美国日期,以毫秒为单位:
using (var file = new StreamWriter("test.csv"))
{
var writer = new CsvWriter(file);
writer.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");
writer.Configuration.RegisterClassMap<CsvMap>();
writer.WriteRecords(items);
}
using (var file = new StreamReader("test.csv"))
{
var reader= new CsvReader(file);
reader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US");
reader.Configuration.RegisterClassMap<CsvMap>();
var models=reader.GetRecords<MyModel>().ToArray();
Console.WriteLine(models[0]);
}
Date,ID
10/12/2017 11:56:11.016,1
10/11/2017 11:56:11.021,2
如果您不想为整个文件设置文化,也可以将CultureInfo指定为TypeConverterOption:
public CsvMap()
{
Map(m => m.Date).TypeConverterOption("MM/dd/yyyy HH:mm:ss.fff")
.TypeConverterOption(CultureInfo.GetCultureInfo("en-US"));
Map(m => m.ID);
}
注意强>
CsvHelper最近发布了一个重大更新(3.0)(如本周)。上周不在场!目前的版本是3.2.0。
在此版本中,CsvClassMap
变为CsvMap
,TypeConverterOptions方法成为具有返回MapMember的方法的对象:
public CsvMap()
{
string format="MM/dd/yyyy HH:mm:ss.fff";
var enUS=CultureInfo.GetCultureInfo("en-US");
Map(m => m.Date).TypeConverterOption.Format(format)
.TypeConverterOption.CultureInfo(enUS);
Map(m => m.ID);
}
仍然没有Type Converters的文档,更不用说TypeConverterOptions了。我找到了this Github issue中的方法,该方法应作为文档。
另一种选择是检查the source code本身。
答案 1 :(得分:0)
public override object ConvertFromString(TypeConverterOptions options, string text)
{
if (string.IsNullOrEmpty(text)) return null;
return Convert.ToDateTime(text);
}
您可能在这里错过了特殊格式。我是DateTime.TryConvert(...)的粉丝 - 我不喜欢Convert.XXXX。是否有理由使用特定类型的转换方法?
答案 2 :(得分:-1)