如何使用CsvEngine.CsvToDataTable()修剪所有列值?

时间:2018-11-26 16:43:34

标签: c# filehelpers

我正在使用 FileHelpers 3.3.1 导入CSV数据并在c#应用程序中填充DataTables。它运作良好,这就是我的称呼方式:

DataTable dt = CsvEngine.CsvToDataTable(fullPath, ',');

问题是某些列值带有填充,例如在值的左侧和/或右侧的空格中,并且这些空格没有被修剪。我的CSV文件很大,并且导入器应用程序的性能很重要,因此我真的想避免事实发生后遍历数据表并修剪每一行的每一列值。

在调用CsvToDataTable()期间是否可以调用“自动修剪所有列值”?

我知道有一个FieldTrim attribute可以做到这一点,但是我无法将刚性类绑定到我的CSV文件,因为我有很多不同的CSV文件,而且它们都有不同的列名和数据类型。所以这对我来说不是一个实际的选择。似乎将有一种内置的方式来使用trim之类的通用CSV解析器之一来CsvToDataTable()

我最好的选择是什么?

1 个答案:

答案 0 :(得分:1)

FileHelpers CsvEngine类非常有限。这是一个sealed类,因此您不能轻松地继承或覆盖它。

如果您不介意hacky解决方案,则可以使用以下方法

// Set the internal TrimChars via reflection
public static class FileBaseExtensions
{
    public static void SetTrimCharsViaReflection(this FieldBase field, Char [] value)
    {
        var prop = typeof(FieldBase).GetProperty("TrimChars", BindingFlags.NonPublic | BindingFlags.Instance);
        prop.SetValue(field, value);
    }
}

CsvOptions options = new CsvOptions("Records", ',', filename);
var engine = new CsvEngine(options);            
foreach (var field in engine.Options.Fields)
{
    field.SetTrimCharsViaReflection(new char[] { ' ', '\t' });
    field.TrimMode = TrimMode.Both;
}
var dataTable = engine.ReadFileAsDT(filename);

但是最好使用标准的FileHelperEngine并创建自己的CsvClassBuilder版本(源代码here)来创建映射类。您必须按以下方式更改AddFields方法:

public override DelimitedFieldBuilder AddField(string fieldName, string fieldType)
{
    base.AddField(fieldName, fieldType);
    if (base.mFields.Count > 1)
    {
        base.LastField.FieldOptional = true;
        base.LastField.FieldQuoted = true;
        base.LastField.QuoteMode = QuoteMode.OptionalForBoth;
        base.LastField.QuoteMultiline = MultilineMode.AllowForBoth;

        // <New>
        base.LastField.TrimMode = TrimMode.Both;
        base.LastField.TrimChars = " \t"; // trim spaces and tabs
        // </New>
    }
    return base.LastField;
} 

如有必要,您可以从hereCsvToDataTable源代码中提取CsvEngine的代码。