Заголовки столбцов в CSV с использованием библиотеки fileHelpers?

Есть ли в библиотеке FileHelper встроенный атрибут поля, который добавит строку заголовка в окончательно сгенерированный CSV?

Я погуглил и не нашел много информации об этом. В настоящее время у меня есть это:

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

Работает, но без шапки.

Я думаю о том, чтобы иметь такой атрибут, как FieldTitleAttribute, и использовать его в качестве заголовка столбца.

Итак, мой вопрос: в какой момент я должен проверять атрибут и вставлять столбцы заголовка? Кто-нибудь делал что-то подобное раньше?

Я хотел бы вставить заголовки и использовать настраиваемый текст, отличный от фактического имени поля, просто имея атрибут для каждого члена объекта:

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

и, возможно, возможность указать движку вставлять заголовок при его создании.

Поэтому, когда вызывается WriteStream или WriteString, строка заголовка будет вставлена ​​с настраиваемыми заголовками.

Я нашел пару событий для DelimitedFileEngine, но не лучший способ определить, является ли текущая запись первой строкой и как вставить строку перед ней.


person Heinnge    schedule 20.10.2010    source источник


Ответы (6)


Вот код, который это сделает: 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?
person Community    schedule 24.11.2011
comment
спасибо за то, что поделились и хорошо поработали. вы хотите добавить класс FieldOrderAttribute для полноты картины? - person Heinnge; 09.02.2012
comment
@Heinnge Класс FieldOrderAttribute находится в библиотеке FileHelpers 2.9.9.0. - person George Stocker; 16.02.2012
comment
Как это отвечает на вопрос, учитывая, что FieldOrder не добавляет заголовок столбца? - person Ian Warburton; 30.08.2013
comment
Это выглядит классным решением, но последний загружаемый пакет на SourceForge - 2.0.0.0, и у него нет FieldOrderAttribute. Этот пакет выпущен в 2007 году, поэтому похоже, что версия 2.9.9.0 никогда не будет официально выпущена. - person mhenry1384; 21.10.2013
comment
Это отлично работает, но в последнем коде он сделал FieldOrderAttribute.Order общедоступным, поэтому ваш код GetOrder () должен немного измениться с NonPublic на Public. Мне также непонятно, почему вы принудительно помещали свой код в его пространство имен, но в любом случае, спасибо за решение, оно прекрасно работает! - person Scott Gartner; 14.04.2014
comment
@GeorgeStocker Добавьте FileHelpersTypeExtensions.cs, и FieldOrder будет доступен в версии 2.0 - person bjan; 21.08.2014
comment
@ScottGartner, потому что методы расширения должны быть легко обнаруживаемыми, а не поиском сокровищ. - person Richard Dingwall; 03.12.2014

Я знаю, что это старый вопрос, но вот ответ, который подходит для версии 2.9.9.

FileHelperEngine<Person> engine = new FileHelperEngine<Person>();
engine.HeaderText = engine.GetFileHeader();
person KiwiPiet    schedule 18.03.2014
comment
Это также рекомендованный подход в их FAQ: filehelpers.net/mustread в разделе «Я хочу написать файл с заголовками - person Colin; 16.02.2016
comment
Это должен быть выбранный ответ. - person Jaxidian; 14.11.2017
comment
Чтобы переопределить заголовки столбцов по умолчанию, создаваемые GetFileHeader(), украсьте поля атрибутом [FieldCaption]. - person Carl Heinrich Hancke; 14.06.2019

Я не знаю, нужно ли вам это еще, но вот как работает FileHelper: чтобы включить заголовки столбцов, вам нужно определить строку с заголовками, разделенными так же, как и ваш файл. Например, с "|" как разделитель:

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

Затем при вызове вашего движка:

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

Если вы не хотите писать заголовки, просто не устанавливайте атрибут HeaderText в движке.

person Saaman    schedule 28.01.2011
comment
спасибо, Сааман. Я заканчиваю тем, что пишу настраиваемый атрибут для этого и дополнительных методов расширения, которые генерируют столбец заголовка. - person Heinnge; 31.01.2011
comment
@CDeutsc У меня больше нет кода с собой. Но я создал простой атрибут [FieldTitleAttribute (Custom Title)], отключил встроенные заголовки и воссоздал заголовок с настраиваемым заголовком (если есть), в противном случае с именами полей по умолчанию. - person Heinnge; 02.06.2011

Просто чтобы включить более полный пример, который сэкономил бы мне время, для версии 3.4.1 пакета FileHelpers NuGet ....

Данный

[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
person David Yates    schedule 03.03.2020

Я обнаружил, что для этого можно использовать FileHelperAsyncEngine. Предполагая, что ваши данные представляют собой список под названием «output» типа «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();
person Roger    schedule 29.06.2011

person    schedule
comment
Несколько более простая конструкция для получения имен полей: var headerText = String.Join (,, typeof (MyClass) .GetFields (). Select (f = ›f.Name) .ToList ()); Движок FileHelperEngine = новый FileHelperEngine ‹MyClass› () {HeaderText = headerText}; - person Scott Gartner; 13.03.2014