Несколько структур CSV с FileHelpers

Я делаю сайт, который использует файл csv, этот файл может быть в двух форматах (возможно, в будущем будет больше).

Структура 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 (если смотреть на raw, все будет разделено запятыми)

Причина, по которой я хочу иметь 2 структуры, заключается в том, что я пытаюсь использовать сторонний сайт, с которого пользователь может экспортировать свои данные. Этот сайт экспортирует его как файл csv с заголовками первой строки. На самом деле меня интересуют только 2 заголовка, и в настоящее время сброс не требуется (но вам нужно экспортировать все столбцы, которые нельзя выбрать и выбрать).

Вторая структура - если пользователь не желает использовать этот сайт, потому что он этого не хочет, ему неудобно это делать и т. Д. У них есть возможность открыть excel up и записать данные вручную, а затем сохранить их как csv. файл.

Поэтому для людей, не занимающихся физическим трудом, я хочу сделать это как можно проще, как будто я не использую данные заголовка 2 и заголовка 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[];
        }



    }

person chobo2    schedule 10.01.2012    source источник


Ответы (2)


Вот несколько предлагаемых подходов:

Прочтите первую строку файла (за пределами 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)

person shamp00    schedule 10.01.2012
comment
Да, первый способ был тем способом, которым я думал, что в конечном итоге сделаю это, но мне нравится ваш второй способ. Как заполняется запись? и для чего используются параметры двигателя? - person chobo2; 10.01.2012
comment
Движок FileHelper заполняет их за вас. Функция CustomSelector - это делегат, который механизм FileHelpers вызывает для каждой записи. Он заполнит engine собой и record текущей записью, а затем будет использовать возвращенные вами Type, чтобы определить, какие из Format1 и Format2 использовать. - person shamp00; 10.01.2012
comment
В порядке. Думаю, сразу приступлю к реализации. В этом будет больше смысла. - person chobo2; 10.01.2012
comment
Итак, как мне позже выяснить, какой объект использовать? Должен ли я для каждой записи a as и видеть, что она может быть приведена к этому объекту? - person chobo2; 12.01.2012
comment
Нет, параметр record в делегате CustomSelector - это string. Он представляет собой строку в вашем формате импорта. Вы должны предоставить некоторую логику, которая определяет, какой класс FileHelpers использовать на основе содержимого строки (в приведенном мной примере я предлагал подсчитывать запятые, но вы можете использовать любые костюмы). Делегат CustomSelector должен возвращать Type класса FileHelpers, который должен использоваться для строки. Здесь может помочь пример. - person shamp00; 12.01.2012
comment
Но всегда ли он берет первую запись и передает ее в customSelector? - person chobo2; 12.01.2012
comment
Также в примере они просто используют массив объектов, но никогда не преобразуют его в класс. CustomSelector может возвращать тип, который возвращается в RecordTypeSelector? Я вижу движок. RecordType - это то, что мне следует использовать? - person chobo2; 12.01.2012

С FileHelpers вам нужно знать формат заранее.

Это означает, что вам нужно будет определить (используя описанный вами метод), в каком формате находится файл, прежде чем использовать FileHelpers для его анализа.

person NotMe    schedule 10.01.2012