Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
0 / 0 / 0
Регистрация: 12.05.2017
Сообщений: 5

Разбор текстовых файлов. Архитектура

12.05.2017, 10:38. Показов 1796. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
надо разобрать текстовый файл с структурированными разношерстными данными (с вложенносятми и т.д.)
Сделал модели под каждый возможный тип данных
Sheet
Component
Parameter
Text
Designator
и т.д. десятка полтора. У каждого куча свойств (имена у части свойств совпадают)
Оформил все в виде фабричного метода.
Сам тектовый файл разбит на строки, одна строка одна запись.
Спарсил ее, получил список словарей, где каждый атрибут строки разбит на ключ:значение.
Вопрос, как праивльно организовать из данных в парсере, полноценную модель данных.
Точнее где организховать заполнение моделей данными.
C#
1
2
3
4
public static class DataReadSchService
{
        private static List<LinePars> _ascii;
}
ну и вот прмиерная реализация LinePars
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class LinePars
{
    public Dictionary<string, string> Properties;
 
    public LinePars()
    {
        Properties = new Dictionary<string, string>();
    }
 
    public void AddProp(string name, string value)
    {
        var nameUp = name.ToUpper();
 
        if (Properties.ContainsKey(nameUp))
        {
            Properties[nameUp] = value;
        }
        else
        {
            Properties.Add(nameUp, value);
        }
    }
 
    public bool Check(string prop)
    {
        return Properties.ContainsKey(prop);
    }
 
    public string Get(string prop)
    {
        return Equals(Properties[prop],"*") ? string.Empty : Properties[prop];
    }
 
    public int GetInt(string prop)
    {
        return Convert.ToInt32(Properties[prop]);
    }
 
    public Boolean GetBool(string prop)
    {
        return Equals(Properties[prop],"TRUE");
    }
}
ну и допустим, перебираю я в цикле все "строки"
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (_ascii.Count == 0) return;
if (!_ascii.First().Check("WEIGHT")) return;
var weight = _ascii.First().GetInt("WEIGHT"); //заголовок
 
 _sheet = (Sheet)_store.PrepareObject(_ascii[1]);
 
for (int i = 2; i < weight; i++)
{
    var tempObj = _store.PrepareObject(_ascii[i]);
 
    if (tempObj != null)
    {
        _sheet.Add(tempObj);
    }
}
Где и как с архитектурной точки зрения, правильно будет заполнять свойства tempObj остальными данными из _ascii ? имена свойств у разных объектов совпадают, а вот их перечень - разный. Плюс некоторые объекты (за графическую часть отвчающие) являются дочерними (тут исопльзую компановщик).
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.05.2017, 10:38
Ответы с готовыми решениями:

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

создание текстовых файлов в C#
Прочитал почти всю веку форума, вроде что-то и есть по работе с файлами но ни как не могу все сложить воедино, уже голова как чугунок...

Перекодирование текстовых файлов
Необходимо написать программу которая сможет: 1)определить в какой кодировке текстовый файл\лы 2)поменять кодировку текстового...

6
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
12.05.2017, 11:09
Цитата Сообщение от mojijrsg Посмотреть сообщение
Где и как с архитектурной точки зрения, правильно будет заполнять свойства tempObj остальными данными из _ascii ? имена свойств у разных объектов совпадают, а вот их перечень - разный. Плюс некоторые объекты (за графическую часть отвчающие) являются дочерними (тут исопльзую компановщик).
Во-первых архитектура тут не при чем, это больше технический вопрос.
В-вторых, ответ зависит от того, чего вы хотите добиться.
Если вам просто нужно сделать парсинг строк в рамках приличий ООП, то сделайте так: в каждом классе (Sheet, Component, Parameter и т.д.) сделайте статический метод Parse(), который будет парсить строку и возвращать заполненный объект нужного типа. Например:
C#
1
2
3
4
5
6
7
8
9
class Sheet
{
   public static Sheet Parse(string line)
   {
       var result = new Sheet();
       //...
       return result;
   }
}
Это стандартный подход, используется везде во фреймворке.

Если же ваша цель сделать более универсально и с меньшим кодом - то через рефлексию.
Создаете парсер, он создает объект нужного типа, пробегается по ключам строки, и через рефлекшн заносит данные в объект. Псевдокодом примерно так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Parser
{
   public IEnumerable<object> ParseLines(IEnumerable<string> lines)
   {
      foreach(var line in lines)
      {
            var className = ExtractClassName(line);//определяем имя нужного класса каким то образом
            var result = Activator.CreateInstance(className);//создаем экземпляр нужного класса
            //пробегаемся по параметрам, заносим в объект
            foreach(var keyValuePair in GetPairs(line))
               result.GetType().GetProperty(keyValuePair.Key).SetValue(result, keyValuePair.Value);
            //возвращаем объект во внешний мир
            yield return result;
       }
   }
}
PS Все это без учета компоновщика. Я не знаю, как оно у вас реализовано в модели и в файле, поэтому затрудняюсь с ответом.
0
0 / 0 / 0
Регистрация: 12.05.2017
Сообщений: 5
12.05.2017, 11:43  [ТС]
в файле примерно такое
Code
1
2
3
4
5
6
7
8
9
|HEADER=Bla bla bla|WEIGHT=8|ID=IVJMUHBQ
|RECORD=Sheet|...атрибуты...
|RECORD=Param|...атрибуты...|ID=CLXRIUDW
|RECORD=Comp|INDEX=1|...еще атрибуты...|ID=VFQNTQES
|RECORD=Param|OWNER=1|...еще атрибуты...|ID=PEHOVHVB
|RECORD=Param|OWNER=1|...еще атрибуты...|ID=UGIDVEIN
|RECORD=Comp|INDEX=2|...еще атрибуты...|ID=QNCMSHMN
|RECORD=Param|OWNER=2|...еще атрибуты...|ID=DTRPKSDY
|RECORD=Param|OWNER=2|...еще атрибуты...|ID=EOSCGOGY
и т.д. и т.п.
т.е. у части объектов спокойно могут пересекаться такие свойства как Color, AreaColor, FontId и прочее прочее.
Если сделать метод статичный, то получится так
C#
1
2
3
4
5
6
7
8
9
10
11
12
   public static Sheet Parse(LinePars line)
   {
       var result = new Sheet();
       
       result.AreaColor = line.Check("AREACOLOR") ? line.GetInt("AREACOLOR") : 0;
 
       result.Color = line.Check("COLOR") ? line.GetInt("COLOR") : 0;
       
       // ...
 
       return result;
   }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
   public static Rectangle Parse(LinePars line)
   {
       var result = new Sheet();
       
       result.AreaColor = line.Check("AREACOLOR") ? line.GetInt("AREACOLOR") : 0;
 
       result.Color = line.Check("COLOR") ? line.GetInt("COLOR") : 0;
      
       // ...
 
 
       var x = line.Check("LOCATION.X") ? line.GetInt("LOCATION.X") : 0;
       var y = line.Check("LOCATION.Y") ? line.GetInt("LOCATION.Y") : 0;
 
       result.Location = new Point(x, y);
 
       var cx = line.Check("CORNER.X") ? line.GetInt("CORNER.X") : 0;
       var cy = line.Check("CORNER.Y") ? line.GetInt("CORNER.Y") : 0;
 
       Corner = new Point(cx, cy);
       
       // ...
       
       return result;
   }
получается много дублирующихся вещей, причем один в один (тут например AreaColor и Color ) Это нормально, или однозначно надо перепиливать?

П.С.: почитаю про рефлексию.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
12.05.2017, 13:28
Цитата Сообщение от mojijrsg Посмотреть сообщение
|RECORD=Comp|INDEX=1|...еще атрибуты...|ID=VFQNTQES
Ну значит в процессе парсинга создаете Dictionary<int, object> в котором храните созданные объекты по их INDEX. Затем, если встречается строка с OWNER - ищите соотв объект в словаре и присоединяете параметр к найденному объекту.
Цитата Сообщение от mojijrsg Посмотреть сообщение
получается много дублирующихся вещей, причем один в один (тут например AreaColor и Color ) Это нормально, или однозначно надо перепиливать?
Это не дублирующиеся вещи, поскольку обращение идет к полям разных классов. Это нормально, но немного громоздко. Рефлексия - сократит код, но там есть другие проблемы. Это не очень ООП-тру, медленнее, и черевато разными проблемами (требование иметь конструктор без параметров, классы должны иметь определенную структуру - например хранить данные только в свойствах, сложнее поддерживать версионность и т.п.).
1
134 / 130 / 107
Регистрация: 17.03.2009
Сообщений: 364
12.05.2017, 16:21
Цитата Сообщение от Storm23 Посмотреть сообщение
требование иметь конструктор без параметров, классы должны иметь определенную структуру - например хранить данные только в свойствах
Это не обязательно.
0
0 / 0 / 0
Регистрация: 12.05.2017
Сообщений: 5
25.05.2017, 16:51  [ТС]
Storm23, столкнулся с интересным моментом, при сериализации.
пусть будет вот такой пример
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    [DataContract]
    [KnownType(typeof(Ellipse ))]
    [KnownType(typeof(Line))]
    [KnownType(typeof(Component))]
    public abstract class CompObject
    {
        public Record Record { get; set; }
    }
 
    public interface IComposite
    {
        void Add(CompObjectcompObject);
        void Remove(CompObjectcompObject);
        ICollection<CompObject> Children();
    }
 
    public class Ellipse : CompObject
    {
        // всякие свойства
 
        public Ellipse ()
        {
            Record = Record.Component;
        }
    }
 
    public class Line: CompObject
    {
        // всякие свойства
 
        public Line()
        {
            Record = Record.Component;
        }
    }
 
    [DataContract]
    public class Component: CompObject, IComposite
    {
        [DataMember]
        public int Color { get; set; }
        [DataMember]
        public int Fill { get; set; }
        [DataMember]
        private List<CompObject> _geometries  = new List<AltiumObject>();
 
        public void Add(CompObject compObject)
        {
            _geometries.Add(compObject);
        }
        public void Remove(CompObject compObject)
        {
            _geometries.Remove(compObject);
        }
 
        public ICollection<CompObject> Children()
        {
            return _geometries ;
        }
 
        public Component()
        {
            Record = Record.Component;
        }
    }
проблема такая, сделал сериализацию, все сохранилось, в файле как надо. А при десериализации, Ellipse , Line - всё как надо. А Component которому пришлось прописывать самому DataContract и DataMember (из-за приватного _geometries), дессериализуется не верно. Record не восстанавливается. Что надо дописать? нагуглить что то у меня не получается
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
25.05.2017, 17:29
Лучший ответ Сообщение было отмечено mojijrsg как решение

Решение

Цитата Сообщение от mojijrsg Посмотреть сообщение
дессериализуется не верно. Record не восстанавливается
у вас не прописан атрибут DataMember для Record. Нужно так:
C#
1
2
3
4
5
6
7
8
9
    [DataContract]
    [KnownType(typeof(Ellipse ))]
    [KnownType(typeof(Line))]
    [KnownType(typeof(Component))]
    public abstract class CompObject
    {
        [DataMember]
        public Record Record { get; set; }
    }
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.05.2017, 17:29
Помогаю со студенческими работами здесь

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

Перемещение текстовых файлов
Здравствуйте. Задание: мне нужно переместить программно по такому признаку - в имени текстового файла (только имя, без расширения)...

Чтение и запись текстовых файлов
Дан текстовый файл (in.txt) содержащий список учащихся и их оценки по трем предметам: математике, физике, информатике. Формат...

Чтение и обработка текстовых файлов
Имеется текстовый файл, содержащий строки, первые символы которых обозначают различные типы данных (они обозначаются типа РА, СА и т.д.),...

Удалить строки из текстовых файлов
foreach (var results in from first in File.ReadLines(@&quot;C:\Users\LowFrequencySound\Desktop\1.txt&quot;) from second...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru