Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > файл проекта и сериализация


Автор: mrgloom 26.10.2012, 15:26
Вообщем есть файл проекта в который записывается куча данных-настройки и т.д. и есть ф-ии Load и Save.
но у программы есть версии, а файлы проекта у версий разные, так вот хотелось бы сделать обратную совместимость.

сейчас это всё читается в стиле 

Код

File f;
    if( !f.open(fileName, _T("rb")) )
        return false;

    const BYTE* p = f.mapping_mem(),
              * fileEnd = p + f.size();


и там в коде для каждой версии каскады If'ов 
Код

if(ver>1.01)
  if(ver>1.02)

и т.д. 

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

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

так вот вопрос как это всё реализуется по человечески?

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

Автор: tzirechnoy 26.10.2012, 16:07
Цитата
так вот вопрос как это всё реализуется по человечески?


По-человечески это сериализуется в текст. Человекочитаемый. Старые версии обычно обламываются, поскольку не знают некоторых новых фич (хотя можно в заголовке объявить какую-то вещь необязательной к пониманию). Новые читают всё, если чего-то нет -- иницыализируют значение по умолчанию.

Автор: Earnest 26.10.2012, 16:19
Вообще, изменение внешнего формата хранения - это довольно больная вещь. Особенно, если программа имеет какое-то внешнее хождение. Формат хранения нужно проектировать очень ответственно - максимально гибко и т.д. Но рано или поздно проблема о конвертации разных версий встает. Чтобы не плодить монстров в коде, лучше все поделить. Т.е. код чтения разных версий - разные классы. По началу файла (заголовку, магическим словам, etc) загрузчик определяет версию файла, создает соответствующий объект-читатель, и передает ему открытый файл. Как-то так.
Разумеется, иногда приходится подружить эти читалки с тем классом (скажем, документа), который они строят... либо надо проектировать очень подробный интерфейс этого самого документа, ... но это уж как кому нравится. Главное - все поделить. Этот подход хорошо масштабируется: скажем, сложный документ может состоять из разных секций, которые тоже в свою очередь могут иметь свои версии (и для каждой своя читалка, и, кстати, писалка заодно).
Обратная совместимость тут, конечно, не работает: небезопасно. Но никто не мешает при небольших изменениях (подверсиях) реализовывать варианты (if) внутри читалки одной версии.

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

Цитата(mrgloom @  26.10.2012,  16:26 Найти цитируемый пост)
видимо тут есть 2 вида как можно хранить: хедер с отступами +тело, либо же хранить всё независимыми блоками, в начале блока запись - сколько необходимо прочитать.

Я за второй вариант: каждый блок (секция) читается-пишется независимо, отдельной читалкой. 
Только мне больше нравится не хранить size в каждом блоке, а иметь отдельный директорий секций (тип, отступ, размер).
Если текущая версия софта ничего не знает, скажем, о конкретном блоке, то она спокойно может его игнорировать, или сохранить в бинарном виде as is. 

Автор: borisbn 26.10.2012, 16:42
А почему формат бинарный, а не xml, например ? В xml по идеологии новые тэги/атрибуты никак не влияют на старые версии программ. Как, впрочем, и наоборот, если задавать, конечно, вменяемые значения по-умолчанию.
В общем, голосую за xml.

Автор: boostcoder 26.10.2012, 17:04
Цитата(borisbn @  26.10.2012,  16:42 Найти цитируемый пост)
xml

он переполнен форматированием.
юзай json.

Автор: borisbn 26.10.2012, 17:09
Цитата(boostcoder @  26.10.2012,  17:04 Найти цитируемый пост)
он переполнен форматированием.
юзай json.

кстати, да. более удобочитаемый формат.
я, правда, для себя недавно открыл XPath, и он замечательно работает на xml (потому и советую).
Говорят на json он тоже есть, но не под Си++

Автор: tzirechnoy 26.10.2012, 17:49
Цитата
В общем, голосую за xml.


Это ужасно. Во-первых, он не человекочитаемый. Во-вторых, те ящерики, которые его разрабатывали, сделали по 5 почти одинаковых вещей для всего, что можно -- но каждая из пяти со своими косяками. Не используйте этот ужас.

Автор: borisbn 26.10.2012, 20:01
> Не используйте этот ужас.
Говорить чего-то НЕ делать не продуктивно

Автор: Randajad 28.10.2012, 15:48
Он привел аргументы, почему это не надо делать.
XML действительно избыточен.

Я бы сделал бинарным.
У каждого значения есть тип и ID. Складировать в вектор struct { int id; bool is_string; union { char str[256]; int val; }; };

Таким образом добавлять новые значения легко. Читать - тоже. Просто искать в векторе. Если нету - значит, конфиг от старой программе, присваиваем этому параметру значение по умолчанию.

Автор: mrgloom 29.10.2012, 09:25
ну я решил переписать на "блоки", но проблема в том, что получается у каждого подблока тоже будет своя версия, например часть где хранится список точек, были просто координаты, а стало например координаты+ цвет. 

Автор: xvr 29.10.2012, 13:55
Используйте XML если размеры данных небольшие. Если же большие, то лучше хранить в виде бинарных тегированных данных. Файл состоит из блоков данных, каждый из которых имеет стандартный заголовок, в который входят тип блока и длинна. Если надо расширить набор данных, просто добавляется новый тип блока. Старый парсер такие блоки будет просто пропускать.

Цитата(mrgloom @  29.10.2012,  09:25 Найти цитируемый пост)
например часть где хранится список точек, были просто координаты, а стало например координаты+ цвет. 

Добавите к старому блоку с координатами новый тип блока с цветами, и все  smile 

Автор: tzirechnoy 31.10.2012, 20:37
Цитата
Говорить чего-то НЕ делать не продуктивно


Ну, вариант JSON здесь ужэ привели. Как формат это всем лучшэ XML. Под XML, конечно, 100500 обезьян написали примерно столько жэ всяких библиотек -- но зачем Вам библиотеки от людей, которые пишут под XML?

Ещё из общего есть s-expressions. Ещё, опять жэ из общего -- netlistы в стиле spice (но оно умеренно читаемое, на самом деле). И графы в стиле graphviz (но к ним парзер не такой простой, да и в итоге получается, что простенький spice-netlist читается чуть не лучшэ, за счёт своей простоты). И C-like описание структур, но уж тут лучшэ JSON.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)