Фактически при выводе объекта в двоичный файл на внешнем носителе осуществляется его «развертывание» в последовательность байтов
Фактически при выводе объекта в двоичный файл на внешнем носителе осуществляется его «развертывание» в последовательность байтов, а при вводе происходит обратный процесс — из последовательности байтов конструируется объект. В объектно-ориентированном программировании придумали специальный термин для обозначения этого процесса: сериализация. Сериализация — это обратимый процесс преобразования произвольного набора структур данных С++ в последовательность байтов. Обратимость означает, что сериализованный объект можно снова «собрать» из последовательности байтов.
Нужно упомянуть об одной важной детали, связанной с двоичным вводом-выводом. Программа, которая считывает информацию из двоичного файла, должна «знать» размер и структуру считываемой информации. При записи в файл туда попадает только та информация, которая явно задана в операторах вывода. Никаких данных о типе выводимого значения на диске нет, если только мы сами их туда не запишем. Поэтому очень просто совершить ошибку: записать в файл объект одного типа, а прочитать записанные байты в переменную другого типа. Например, i nt и f loat в системе Visual C++.NET 2003 занимают в памяти одинаковое количество байтов — четыре. Поэтому в приведенных ранее примерах (см. листинг 14.7) можно было бы записать На диск массив дробных чисел типа float, а считывать его как массив целых чисел. Никаких сообщений об ошибках, естественно, не выдается; программа может даже работать, но результат, как вы понимаете, будет абсолютно неверным. Поэтому функции ввода-вывода обычно разрабатываются «парами»: одна — для записи в файл, другая — для чтения из файла.
Никто не знает структуру объекта лучше, чем сам объект. Поэтому, если требуется сохранить объект на диске, можно в классе реализовать два метода: save() и load(). Методы save() и load(), очевидно, должны быть симметричными — процесс сериализации должен быть обратимым. Эти методы должны работать с полями объекта. Например, для класса TDate (см. далее раздел «Перегрузка операций ввода-вывода») требуется выводить поля
unsigned long date; static fmtflags fmt;
Один из вариантов реализации методов save() и load() позволяет создать «моментальный снимок» объекта во внешней памяти, который в дальнейшем можно восстановить. Прототипы методов выглядят просто:
void saveQ ; void load();
В методе save() нужно определить локальный выходной поток и открыть его как двоичный. Поток, естественно, должен быть связан с файлом, который метод load () через свой локальный поток должен открывать как входной. Поэтому оба метода должны как-то получить доступ к одному и тому же имени файла. Очевидно, что этот файл может быть временным. Так как имя файла не должно совпадать с именем никакого другого файла, файл можно создать с помощью стандартной функции tmpnam() из библиотеки <cstdio>. Прототип функции:
char *tmpnam(char *s);
В качестве аргумента можно задать массив символов, тогда имя будет сгенерировано в нем. Назначение метода save() понятно, и написать его несложно.
Единственная проблема — передать информацию об имени файла в метод load (). Это проще всего сделать, определив в классе поле, представляющее собой символьный массив, например:
char name[13];
Тогда метод saveQ будет заносить в это поле имя, сгенерированное функцией tmpnam(), а метод load() — открывать файл с этим именем.
Ввод-вывод скалярных объектов относительно прост, так как поля в классе известны и занимают фиксированное количество байтов. Значительно сложнее запрограммировать сериализацию динамических контейнеров, ведь требуется выводить не указатели, а значения, записанные в динамической памяти. Например, для динамического массива ТАггау (см. листинг 6.10) требуется выводить поле-размер size_array и само содержимое динамического массива, расположенного по адресу, записанному в поле-указателе data.
Опубликовал Kest
April 07 2014 14:18:14 ·
0 Комментариев ·
3090 Прочтений ·
• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •
Комментарии
Нет комментариев.
Добавить комментарий
Рейтинги
Рейтинг доступен только для пользователей.
Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.
Нет данных для оценки.
Гость
Вы не зарегистрированны? Нажмите здесь для регистрации.