1

我想知道我是否必须放弃文件助手并自己做这件事,因为我认为我可能超出了它的设计目的。

我希望用户能够上传任何 csv 文件(也许在未来的 excel 文件中)。第一行会有标题

C1 C2 C3 C4 C5 C6

一旦上传它看起来像

C1,C2,C3,C4,C5,C6 a,b,c,d,e,f

现在我想看一下标题,基本上取某些标题。例如我想要C2, C3, C4.其余的都是我不关心的额外信息。

现在有人可能会上传具有此标头的文件

C1 C2 C3 C4

我再次只寻找C2, C3, C4.

我知道我可以有多种格式,但我得到的是我希望他们能够基本上上传任何带有任意数量标题的文件(我关心的可能是 1000 个),然后让我的应用程序尝试找到我的信息关心(所以在 1000 个标题的情况下,我可能只想要 3 个)

这可能吗?

编辑

(基于 shamp00 评论)

我的目标是尽可能多地填写我可以确定的数据,但是这样的情况可能会发生。我想要C1,C2,C3。他们给出了一个带有 C1、C3、C4 的文件。我有 2 列我需要的数据,但我没有 C2。

现在我有 2 个想法,一个是将数据显示到 2 个表中。表 1 将具有 C1、C2、C3,表 2 将具有 C1、C3、C4,它们基本上采用表 2 中的数据并将适当的数据移动到我预期的列中。

使用这种方法,我基本上是在说“你没有给我 100% 的预期,现在你必须将每一行格式化为我的格式”。

第二种方法是 1 个表并尝试填写尽可能多的数据。

例如,用户上传具有 C1、C3、C4 的文件。我确定它们是已知的 2 列,但我还没有全部的预期数据。

所以我会在一个html表中向用户显示所有行,标题为

C1, C2, C3, C4

C1 将被填写,C2 单元格将是空白的(因为这是我缺少的数据),C3 将被填写,C4 将被填写(这个数据是出乎意料的,但谁知道它实际上可能是数据C2 应该保留,但由于他们拼错了标题名称,我的程序无法弄清楚)。

然后基本上他们只会用从其他地方或可能从 C4 获得的数据填充 C2。

现在他们只需要填写 1 列,而不是预期的所有列。所以从某种意义上说,我需要一个具体的类,比如 MyClass 是 C1,C2,C3 但同时我需要动态以便我可以持有C4,C5.....Cn.

我总是首先显示 C1、C2、C3,其余的这些意想不到的将在之后通过 javascript 的魔力和他们可以编辑缺失信息的东西出现。如果没有任何遗漏,则不会显示任何内容进行编辑。

根据 shamp00 评论,我现在想知道是否需要将数据作为数据表返回(幸运的是,这似乎是一个系统类,因为现在我的代码位于服务层中,并且我根据需要返回了域传输类使我的代码独立于类似的网络代码类,因此我试图弄清楚如何生成动态类 FileHelpers。)。

然后不知何故(还不是 100% 确定)只是跟踪我真正感兴趣的那 3 列的位置,这样我就知道哪些数据是什么。

4

2 回答 2

1

您可以使用 FileHelpers 使用我对您的另一个问题的回答中描述的技术。

您阅读标题行以确定哪些列是相关的,然后DataTable仅遍历结果处理这些列。

就像是

public class MyClass
{
    public string SomeImportantField { get; set; }
    public string SomeOtherField { get; set; }
    public string AnotherField { get; set; }
}

public IList<MyClass> GetObjectsFromStream(Stream stream)
{
    var cb = new DelimitedClassBuilder("temp", ",") { IgnoreFirstLines = 1, IgnoreEmptyLines = true, Delimiter = "," };
    var sr = new StreamReader(stream);
    var headerArray = sr.ReadLine().Split(',');
    foreach (var header in headerArray)
    {
        var fieldName = header.Replace("\"", "").Replace(" ", "");
        cb.AddField(fieldName, typeof(string));
    }

    var engine = new FileHelperEngine(cb.CreateRecordClass());

    List<MyClass> objects = new List<MyClass>();
    DataTable dt = engine.ReadStreamAsDT(sr);
    foreach (DataRow row in dt.Rows) // Loop over the rows.
    {
        MyClass myClass = new MyClass();
        for (int i = 0; i < row.ItemArray.Length; i++) // Loop over the items.
        {
            if (headerArray[i] == "ImportantField")
                myClass.SomeImportantField = row.ItemArray[i].ToString();
            if (headerArray[i] == "OtherField")
                myClass.SomeOtherField = row.ItemArray[i].ToString();
            if (headerArray[i] == "AnotherField")
                myClass.AnotherField = row.ItemArray[i].ToString();
            objects.Add(myClass);
        }
    }
    return objects;
}
于 2012-02-09T15:48:35.687 回答
1

我不熟悉 FileHelpers,但我使用名为 LogParser (http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=24659) 的工具完成了与您所描述的非常相似的事情结合我自己的“DelimitedTextFileData”类。如果您认为 FileHelpers 不能满足您的需求,我建议您接下来查看 LogParser。即使它对您当前的项目来说有点矫枉过正,但对于未来的项目来说,它是一个很好的工具。

LogParser 是一种工具,它允许对各种源(包括 CSV 文本文件)进行“类似 SQL”的查询。它是一个基于命令行的 .exe,但还附带一个 API,您可以在 .NET 项目中引用。在我的情况下,我正在处理可以由任何字符分隔的文本文件,因此我开发了自己的类,让我在类实例化时指定分隔符,然后使用一个简单的 API 来利用更大的 LogParser API。我还必须解析具有未知数量(和名称)列的文件,因此我的自定义类具有检索文件中找到的列列表的功能。如果您一直在处理 CSV,并且您确切地知道您想要哪些列,您可能不需要采取这些额外的步骤。不过,如果您愿意,我很乐意分享我的自定义课程;

LogParser 旨在让您“使用类似 SQL 的语法查询任何内容”,我想到 Linq 的一个目的就是做同样的事情。您是否在网上搜索过任何“Linq to Text File”库?如果那里有一个好的,它也可以解决您的问题。

于 2012-02-09T20:44:54.177 回答