Импорт файлов данных с использованием общих определений классов - PullRequest
5 голосов
/ 17 февраля 2011

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

public interface IRecordDefinition<T>
{
    bool Matches(string row);
    T MapRow(string row);
    bool AreRecordsNested { get; }
    GenericLoadClass ToGenericLoad(T input);
}

Затем я создал конкретную реализацию для класса.

public class TestDefinition : IRecordDefinition<Test>
{
    public bool Matches(string row)
    {
        return row.Split('\t')[0] == "1";
    }

    public Test MapColumns(string[] columns)
    {
        return new Test {val = columns[0].parseDate("ddmmYYYY")};
    }

    public bool AreRecordsNested
    {
        get { return true; }
    }

    public GenericLoadClass ToGenericLoad(Test input)
    {
        return new GenericLoadClass {Value = input.val};
    }
}

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

Во-первых, я на правильном пути
или есть лучший способ сделать это?

Ответы [ 3 ]

3 голосов
/ 24 февраля 2011

Я бы разделил этот процесс на две части.

Во-первых, специфический процесс для разделения файла с несколькими типами на несколько файлов. Если файлы фиксированной ширины, мне повезло с регулярными выражениями. Например, предположим, что ниже приведен текстовый файл с тремя различными типами записей.

TE20110223 A 1
RE20110223 BB 2
CE20110223 CCC 3

Вы можете видеть, что здесь есть образец, надеюсь, человек, который решил поместить все типы записей в один файл, дал вам способ идентифицировать эти типы. В случае выше вы бы определили три регулярных выражения.

string pattern1 = @"^TE(?<DATE>[0-9]{8})(?<NEXT1>.{2})(?<NEXT2>.{2})";
string pattern2 = @"^RE(?<DATE>[0-9]{8})(?<NEXT1>.{3})(?<NEXT2>.{2})";
string pattern3 = @"^CE(?<DATE>[0-9]{8})(?<NEXT1>.{4})(?<NEXT2>.{2})";

Regex Regex1 = new Regex(pattern1);
Regex Regex2 = new Regex(pattern2);
Regex Regex3 = new Regex(pattern3);

StringBuilder FirstStringBuilder = new StringBuilder();
StringBuilder SecondStringBuilder = new StringBuilder();
StringBuilder ThirdStringBuilder = new StringBuilder();

string Line = "";
Match LineMatch;


FileInfo myFile = new FileInfo("yourFile.txt");

using (StreamReader s = new StreamReader(f.FullName))
{

    while (s.Peek() != -1)
    {
        Line = s.ReadLine();

        LineMatch = Regex1.Match(Line);
        if (LineMatch.Success)
        {
            //Write this line to a new file
        }

        LineMatch = Regex2.Match(Line);
        if (LineMatch.Success)
        {
            //Write this line to a new file
        }

        LineMatch = Regex3.Match(Line);
        if (LineMatch.Success)
        {
            //Write this line to a new file
        }
    }
}

Затем возьмите разделенные файлы и запустите их через общий процесс, который вы, скорее всего, уже имеете, чтобы импортировать их. Это хорошо работает, потому что, когда процесс неизбежно завершается сбоем, вы можете сузить его до одного типа записи, который дает сбой и не влияет на все типы записей. Архивируйте основной текстовый файл вместе с разделенными файлами, и ваша жизнь также будет намного проще.

Трудно иметь дело с такими типами передаваемых файлов, потому что кто-то еще контролирует их, и вы никогда не знаете, когда они изменятся. Регистрация исходного файла, а также квитанция об импорте очень важны и не должны быть упущены из виду. Вы можете сделать это настолько простым или сложным, насколько захотите, но я склонен записывать квитанцию ​​в БД и копировать первичный ключ из этой таблицы во внешний ключ в таблице, в которую я импортировал данные, тогда никогда изменить эти данные. Мне нравится хранить нематериальную копию импорта в файловой системе, а также на сервере БД, потому что есть неизбежные проблемы преобразования / преобразования, которые вам нужно будет отследить.

Надеюсь, это поможет, потому что это не тривиальная задача. Я думаю, что вы на правильном пути, но вместо обработки / импорта каждой строки в отдельности ... запишите их в отдельный файл. Я предполагаю, что это финансовые данные, что является одной из причин, почему я считаю, что доказуемость на каждом этапе важна.

3 голосов
/ 26 февраля 2011

Я думаю, что библиотека FileHelpers решает ряд ваших проблем:

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

3 голосов
/ 23 февраля 2011

Вы смотрели на что-то, используя Linq ?Это быстрый пример Linq to Text и Linq to Csv.

Я думаю, было бы намного проще использовать «yield return» и IEnumerable, чтобы получить то, что вы хотите, чтобы работало.Таким образом, вы могли бы избежать использования только одного метода в вашем интерфейсе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...