52

FileHelper 库中是否有内置字段属性,它将在最终生成的 CSV 中添加标题行?

我用谷歌搜索并没有找到太多关于它的信息。目前我有这个:

DelimitedFileEngine _engine = new DelimitedFileEngine(T);
_engine.WriteStream
        (HttpContext.Current.Response.Output, dataSource, int.MaxValue);

它有效,但没有标题。

我正在考虑FieldTitleAttribute使用类似的属性并将其用作列标题。

所以,我的问题是在什么时候检查属性并插入标题列?有没有人做过类似的事情?

我想插入标题并使用与实际字段名称不同的自定义文本,只需在对象的每个成员上都有一个属性:

[FieldTitleAttribute("Custom Title")]
private string Name

也许还有一个选项可以告诉引擎在生成标题时插入标题。

所以当WriteStreamorWriteString被调用时,标题行将插入自定义标题。

我为 DelimitedFileEngine 找到了几个事件,但不是检测当前记录是否是第一行以及如何在此之前插入一行的最佳方法。

4

6 回答 6

46

我知道这是一个老问题,但这里有一个适用于 v2.9.9 的答案

FileHelperEngine<Person> engine = new FileHelperEngine<Person>();
engine.HeaderText = engine.GetFileHeader();
于 2014-03-18T19:27:34.210 回答
35

这是一些可以做到的代码:https ://gist.github.com/1391429

[FieldOrder]要使用它,您必须使用(无论如何是一个好的 FileHelpers 实践)来装饰您的字段。用法:

[DelimitedRecord(","), IgnoreFirst(1)]
public class Person
{
    // Must specify FieldOrder too
    [FieldOrder(1), FieldTitle("Name")]
    string name;

    [FieldOrder(2), FieldTitle("Age")]
    int age;
}

...

var engine = new FileHelperEngine<Person>
{
    HeaderText = typeof(Person).GetCsvHeader()
};

...

engine.WriteFile(@"C:\people.csv", people);

但是对此的支持确实需要在 FileHelpers 本身中添加。我可以想到一些在实现之前需要回答的设计问题:

  • 读取文件时会发生什么?Afaik FileHelpers 目前全部基于序号列位置并忽略列名......但如果我们现在[FieldHeader]到处都有属性,那么我们是否也应该尝试将属性与文件中的列名匹配?如果它们不匹配,你应该抛出异常吗?如果序数位置与列名不一致怎么办?
  • 当作为数据表读取时,您应该使用 A) 字段名称(当前设计),还是 B) 源文件列名称,还是 C) FieldTitle 属性?
于 2011-11-24T14:13:50.243 回答
23

我不知道你是否还需要这个,但这是 FileHelper 的工作方式:要包含列的标题,您需要定义一个字符串,其标题与文件的分隔方式相同。例如使用“|” 作为分隔符:

 public const string HeaderLine = @"COLUMN1|COLUMN2|COLUMN3|...";

然后,当调用你的引擎时:

DelimitedFileEngine _engine = new DelimitedFileEngine<T> { HeaderText = HeaderLine };

如果您不想编写标题,请不要HeaderText在引擎上设置属性。

于 2011-01-28T11:19:43.987 回答
6
List<MyClass> myList = new List<MyClass>();
FileHelperEngine engine = new FileHelperEngine(typeof(MyClass));
String[] fieldNames = Array.ConvertAll<FieldInfo, String>(typeof(MyClass).GetFields(), delegate(FieldInfo fo) { return fo.Name; });
engine.HeaderText = String.Join(";", fieldNames);
engine.WriteFile(MapPath("MyClass.csv"), myList);
于 2013-12-09T10:11:00.077 回答
3

只是为了包含一个更完整的示例,这将为我节省一些时间,用于 FileHelpers NuGet 包的 3.4.1 版本......

给定

[DelimitedRecord(",")]
public class Person
{
   [FieldCaption("First")]
   public string FirstName { get; set; }

   [FieldCaption("Last")]
   public string LastName { get; set; }

   public int Age { get; set; }
}

和这个代码来创建它

static void Main(string[] args)
{
    var people = new List<Person>();
    people.Add(new Person() { FirstName = "James", LastName = "Bond", Age = 38 });
    people.Add(new Person() { FirstName = "George", LastName = "Washington", Age = 43 });
    people.Add(new Person() { FirstName = "Robert", LastName = "Redford", Age = 28 });

    CreatePeopleFile(people);
}

private static void CreatePeopleFile(List<Person> people)
{
    var engine = new FileHelperEngine<Person>();

    using (var fs = File.Create(@"c:\temp\people.csv"))
    using (var sw = new StreamWriter(fs))
    {
        engine.HeaderText = engine.GetFileHeader();
        engine.WriteStream(sw, people);
        sw.Flush();
    }
}

你得到这个

First,Last,Age
James,Bond,38
George,Washington,43
Robert,Redford,28
于 2020-03-03T16:30:37.317 回答
1

我发现您可以使用 FileHelperAsyncEngine 来完成此操作。假设您的数据是类型为“outputData”的名为“输出”的列表,那么您可以编写如下所示的代码:

        FileHelperAsyncEngine outEngine = new FileHelperAsyncEngine(typeof(outputData));
        outEngine.HeaderText = "Header1, Header2, Header3";
        outEngine.BeginWriteFile(outputfile);
        foreach (outputData line in output){
            outEngine.WriteNext(line);
        }
        outEngine.Close();
于 2011-06-29T23:52:10.403 回答