C# 解析CSV,其中头包含带有CsvHelper的空格

C# 解析CSV,其中头包含带有CsvHelper的空格,c#,csv,csvhelper,C#,Csv,Csvhelper,我有一个带有字段标题的CSV文件,其中一些文件包含两个或三个用空格分隔的单词: 您可以在上图中看到包含空格的字段标题: “时间”、“进程名称”和“映像路径” 当我试图通过调用reader.GetRecords()读取CSV时(其中,DataRecord是我定义的一个类),我得到错误: CSV文件中不存在“TimeOfDay”字段。“* 这是因为我的DataRecord类不能包含带有空格的成员 如何使用CsvHelper解析CSV文件?基于CsvHelper,有几种方法可以实现我们想要的结果 1

我有一个带有字段标题的CSV文件,其中一些文件包含两个或三个用空格分隔的单词:

您可以在上图中看到包含空格的字段标题:
“时间”、“进程名称”和“映像路径”

当我试图通过调用
reader.GetRecords()读取CSV时
(其中,
DataRecord
是我定义的一个类),我得到错误:

CSV文件中不存在“TimeOfDay”字段。“*

这是因为我的
DataRecord
类不能包含带有空格的成员

如何使用CsvHelper解析CSV文件?

基于CsvHelper,有几种方法可以实现我们想要的结果

1.忽略标题中的空白(我相信这会很容易解决您的问题)

在CsvHelper 3或更高版本中,使用
prepareHeadPerformatch
(记录在)删除标题中的空白:

csv.Configuration.PrepareHeaderForMatch =
    header => Regex.Replace(header, @"\s", string.Empty)
在CsvHelper 2中,设置
IgnoreHeaderWhiteSpace
标志,告知读者在按名称将列与属性匹配时忽略标题中的空白

reader.Configuration.IgnoreHeaderWhiteSpace = true;
2.手动读取

我们可以手动读取每个字段,如:

var reader = new CsvReader(sr);
do
{
    reader.Read();                   
    var record=new DataRecord();

    record.TimeOfDay=reader.GetField<string>("Time of Day");
    record.ProcessName=reader.GetField<string>("Process Name");
    record.PID=reader.GetField<string>("PID");
    record.Operation=reader.GetField<string>("Operation");
    record.Path=reader.GetField<string>("Path");
    record.Result=reader.GetField<string>("Result");
    record.Detail=reader.GetField<string>("Detail");
    record.ImagePath=reader.GetField<string>("Image Path");

} while (!reader.IsRecordEmpty());
然后,我们应使用以下方式进行注册:

reader.Configuration.RegisterClassMap<DataRecordMap>();
reader.Configuration.RegisterClassMap();
该库现在支持。您可能希望使用该属性

using CsvHelper.Configuration.Attributes;

public class DataRecord
{
    [Name("Time of Day")]
    public string TimeOfDay { get; set; }

    [Name("Process Name")]
    public string ProcessName { get; set; }

    public string PID { get; set; }
    public string Operation { get; set; }
    public string Path { get; set; }
    public string Result { get; set; }
    public string Detail { get; set; }

    [Name("Image Path")]
    public string ImagePath { get; set; }

    public static IEnumerable<DataRecord> ParseDataRecords(Stream file)
    {
        using (var sr = new StreamReader(file))
        using (var csv = new CsvReader(sr))
        {
            foreach (var record in csv.GetRecords<DataRecord>())
            {
                yield return record;
            }
        }
    }
}
使用CsvHelper.Configuration.Attributes;
公共类数据记录
{
[名称(“一天中的时间”)]
公共字符串TimeOfDay{get;set;}
[名称(“流程名称”)]
公共字符串ProcessName{get;set;}
公共字符串PID{get;set;}
公共字符串操作{get;set;}
公共字符串路径{get;set;}
公共字符串结果{get;set;}
公共字符串详细信息{get;set;}
[名称(“图像路径”)]
公共字符串ImagePath{get;set;}
公共静态IEnumerable ParseDataRecords(流文件)
{
使用(var sr=新的StreamReader(文件))
使用(var csv=新的CsvReader(sr))
{
foreach(csv.GetRecords()中的var记录)
{
收益回报记录;
}
}
}
}

虽然看起来不错,但方法1似乎不再起作用。预期的函数现在需要两个参数。添加一个参数后,返回值似乎没有被使用,该方法没有任何效果。@kjyv我使用
csv.Configuration.prepareHeadPerformatch=(header,index)=>Regex.Replace(header,index)=>Regex.Replace(header,@“\s使其工作起来“,字符串。空)只是好奇是否有人编写了一个“列名不匹配调试器”,这样它就不会抛出一个错误,说它找不到匹配项,而是尝试查找与映射中的任何单词匹配的任何列。例如,我有一个名为“RatingAgency”的专栏,但得到一个错误消息:什么都不存在。虽然我希望它在开发过程中很难失败,但我也希望它在开发过程中说:“哦,嘿,约翰,以下专栏部分匹配:“评级机构,评级”
using CsvHelper.Configuration.Attributes;

public class DataRecord
{
    [Name("Time of Day")]
    public string TimeOfDay { get; set; }

    [Name("Process Name")]
    public string ProcessName { get; set; }

    public string PID { get; set; }
    public string Operation { get; set; }
    public string Path { get; set; }
    public string Result { get; set; }
    public string Detail { get; set; }

    [Name("Image Path")]
    public string ImagePath { get; set; }

    public static IEnumerable<DataRecord> ParseDataRecords(Stream file)
    {
        using (var sr = new StreamReader(file))
        using (var csv = new CsvReader(sr))
        {
            foreach (var record in csv.GetRecords<DataRecord>())
            {
                yield return record;
            }
        }
    }
}