【问题标题】:Multiple CSV structures with FileHelpers具有 FileHelpers 的多个 CSV 结构
【发布时间】:2012-01-10 00:25:52
【问题描述】:

我正在制作一个使用 csv 文件的网站,该文件可以有 2 种格式(将来可能会更多)。

结构 1

Header 1 Header 2 Header 3 Header 4 
a          b      c       d
x          x      x       x

结构2

Header 1 Header 4
a          d
x          x

以上是它在excel中的显示方式(如果查看原始数据,它将全部用逗号分隔)

我想要 2 个结构的原因是因为我正在尝试利用用户可以从中导出数据的 3rd 方站点。该站点将其导出为 csv 文件,第一行是标题。我真的只关心 2 个标题,目前不需要重置(但您必须导出所有无法选择的列)。

第二个结构是如果用户不想使用这个网站,因为他们不想,不舒服这样做等等。他们可以选择打开 Excel 并手动写入数据,然后保存它作为 csv 文件。

因此,对于手动操作的人,我想让它尽可能简单,就好像我不使用 Header 2 和 Header 4 数据一样,我为什么要费心让他们输入呢?然而,与此同时,如果人们通过第一种方式并导出数据,我不希望他们不得不将文件加载到 excel 中并删除 2 列。

我将要求标题必须始终完好无损并且位于第一行。我想出的唯一想法是阅读第一行并查看标题的顺序。如果它有 4 个按确切顺序排列的标头,则以一种方式呈现。如果该顺序中只有 2 个标题以另一种方式呈现。

我知道FileHelpers 有能力做多个定界符并选择如何呈现它,但由于我正在查看标题,我不确定这是否已经融入,或者我是否需要以某种方式自己编写然后告诉它怎么办。

有没有人知道我是否可以使用文件助手来做到这一点?

编辑 这就是我目前所拥有的

MultiRecordEngine engine = new MultiRecordEngine(typeof(Format2), typeof(Format1));
    engine.RecordSelector = new RecordTypeSelector(CustomSelector);

    using (TextReader textReader = new StreamReader(stream))
    {
        if (engine.RecordType == typeof(Format2))
        {
            var myArry = engine.ReadStream(textReader) as Format2[];

        }
        else if(engine.RecordType == typeof(Format1))
        {
            var myArry = engine.ReadStream(textReader) as Format1[];
        }



    }

【问题讨论】:

    标签: c# csv filehelpers


    【解决方案1】:

    以下是一些建议的方法:

    读取文件的第一行(在 FileHelpers 之外)并确定创建引擎之前使用哪种格式

    if (firstLineOfFile.Contains("Header 2"))
        FileHelperEngine engine = new FileHelperEngine(typeof(Format1)); 
    else
        FileHelperEngine engine = new FileHelperEngine(typeof(Format2)); 
    

    或者,您可以使用MultiRecordEngine

    MultiRecordEngine engine;  
    engine = new MultiRecordEngine(typeof(Format1), typeof(Format2)); 
    engine.RecordSelector = new RecordTypeSelector(CustomSelector); 
    

    使用类似的选择器方法

    Type CustomSelector(MultiRecordEngine engine, string record) 
    { 
        // count the separators to determine which format to return
        int separatorCount = record.Count(f => f == ',');
        if (separatorCount == 4) 
            return typeof(Format1); 
        else 
            return typeof(Format2); 
    } 
    

    (MultiRecordEngine 将来可以处理更多格式 - 它有一个带有params 参数的构造函数)

    【讨论】:

    • 是的,第一种方式是我认为我最终会这样做的方式,但我喜欢你的第二种方式。记录如何填写?引擎参数是做什么用的?
    • FileHelper 引擎会为您填充它们。 CustomSelector 函数是 FileHelpers 引擎为每条记录调用的委托。它将使用自身填充engine,并使用当前记录填充record,然后它将使用您返回的Type 来确定要使用Format1Format2 中的哪一个。
    • 好的。我想一旦我开始实施它。这会更有意义。
    • 那么我以后如何弄清楚要使用什么对象呢?我是否必须为每条记录添加一个“as”并查看它是否可以转换为该对象?
    • 不,CustomSelector 委托中的record 参数是string。它代表导入格式中的一行。您必须提供一些逻辑,根据行的内容确定要使用哪个 FileHelpers 类(在我提供的示例中,我建议计算逗号,但您可以使用任何适合的东西)。 CustomSelector 委托必须返回 FileHelpers 类的 Type,它应该用于行。 example 这里应该有帮助。
    【解决方案2】:

    使用 FileHelpers,您需要提前知道格式。

    这意味着在使用 FileHelpers 解析文件之前,您必须检测(使用您描述的方法)文件的格式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-10
      • 1970-01-01
      • 2016-04-25
      • 2018-10-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多