首页 > 解决方案 > 如何使用 CsvEngine.CsvToDataTable() 修剪所有列值?

问题描述

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

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

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

有没有办法在调用期间调用“自动修剪所有列值” CsvToDataTable()

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

我最好的选择是什么?

标签: c#filehelpers

解决方案


FileHelpersCsvEngine类非常有限。它是一个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为源代码)来创建映射类。您必须按如下方式更改方法: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;
} 

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


推荐阅读