Уважаемые, прошу вашей помощи. Меня интересует вопрос как записать данные из вектора (в моем случае "vector <Person> pers") данные в файл, чтобы потом их можно было считать. В векторе хранятся только данные о Имени, Фамилии, Дате рождения, Телефоне. Ну и нужно их сохранять, чтобы при каждом запуске программы не вводить всю информацию заново. Прочитал что лучше всего сохранять в бинарный файл, но как реализовать не знаю.Напишите пожалуйста код...
Здравствуйте, Usefur, Вы писали:
U>Уважаемые, прошу вашей помощи. Меня интересует вопрос как записать данные из вектора (в моем случае "vector <Person> pers") данные в файл, чтобы потом их можно было считать. В векторе хранятся только данные о Имени, Фамилии, Дате рождения, Телефоне. Ну и нужно их сохранять, чтобы при каждом запуске программы не вводить всю информацию заново. Прочитал что лучше всего сохранять в бинарный файл, но как реализовать не знаю.Напишите пожалуйста код...
Используйте библиотеку сериализации из Boost, она так и называется — serialization.
Пользоваться очень просто, достаточно определить метод serialize для нужного класса и
использовать перегруженный метод &. Кстати, сериализация для контейнеров типа vector в
Boost уже имеется.
Здравствуйте, okman, Вы писали:
O>Здравствуйте, Usefur, Вы писали:
O>Используйте библиотеку сериализации из Boost, она так и называется — serialization. O>Пользоваться очень просто, достаточно определить метод serialize для нужного класса и O>использовать перегруженный метод &. Кстати, сериализация для контейнеров типа vector в O>Boost уже имеется.
Здравствуйте, Usefur, Вы писали:
U>Здравствуйте, okman, Вы писали:
O>>Здравствуйте, Usefur, Вы писали:
O>>Используйте библиотеку сериализации из Boost, она так и называется — serialization. O>>Пользоваться очень просто, достаточно определить метод serialize для нужного класса и O>>использовать перегруженный метод &. Кстати, сериализация для контейнеров типа vector в O>>Boost уже имеется.
U>Наведите пожалуйста пример
Здравствуйте, okman, Вы писали:
O>Здравствуйте, Usefur, Вы писали:
U>>Уважаемые, прошу вашей помощи. Меня интересует вопрос как записать данные из вектора (в моем случае "vector <Person> pers") данные в файл, чтобы потом их можно было считать. В векторе хранятся только данные о Имени, Фамилии, Дате рождения, Телефоне. Ну и нужно их сохранять, чтобы при каждом запуске программы не вводить всю информацию заново. Прочитал что лучше всего сохранять в бинарный файл, но как реализовать не знаю.Напишите пожалуйста код...
O>Используйте библиотеку сериализации из Boost, она так и называется — serialization. O>Пользоваться очень просто, достаточно определить метод serialize для нужного класса и O>использовать перегруженный метод &. Кстати, сериализация для контейнеров типа vector в O>Boost уже имеется.
Зачем для таких задач нужен буст, если решения подобных задач занимает 30-60 строк?
Здравствуйте, Fedor Sumkin, Вы писали:
FS>Для записи можно использовать write т.к. vector представим в памяти в виде сплошного блока.
FS>Для записи, если не хочется по размеру файла определять размер вектора надо дополнительно записывать размер вектора : FS>
FS>ofstream out ("data.txt", ios::binary);
FS>out.write((char*)&pers.size(), 4);
FS>out.write((char*)&pers[0], pers.size()*sizeof(Person));
FS>out.close();
FS>
На выходе ты гарантировано получишь труху, хорошо если такое рухнет сразу, до того как в программе появится мусор, который начнут писать в базу данных.
Здравствуйте, Fedor Sumkin, Вы писали:
FS>Для записи можно использовать write т.к. vector представим в памяти в виде сплошного блока.
FS>Для записи, если не хочется по размеру файла определять размер вектора надо дополнительно записывать размер вектора :
Подобное допустимо только для сохранения коллекции POD типов.
Здравствуйте, peterbes, Вы писали:
P>Зачем для таких задач [сериализация] нужен буст, если решения подобных задач занимает 30-60 строк?
Не скажите.
Сериализация контейнеров пользовательских типов, да еще с деконструированием-реконструированием
ссылок и указателей на другие объекты, будет занимать отнюдь не 30-60 строк, а на пару порядков больше.
Да и вообще, по большому счету я не вижу причин не использовать Boost, особенно в таких
традиционных задачах. Весь Boost для этого тянуть не надо, к слову говоря.
Здравствуйте, okman, Вы писали:
O>Здравствуйте, peterbes, Вы писали:
P>>Зачем для таких задач [сериализация] нужен буст, если решения подобных задач занимает 30-60 строк?
O>Не скажите. O>Сериализация контейнеров пользовательских типов, да еще с деконструированием-реконструированием O>ссылок и указателей на другие объекты, будет занимать отнюдь не 30-60 строк, а на пару порядков больше. O>Да и вообще, по большому счету я не вижу причин не использовать Boost, особенно в таких O>традиционных задачах. Весь Boost для этого тянуть не надо, к слову говоря.
У бустовских сериализаторов масса своих недостатков, нужно хотя бы читать в той же последовательности в какой данные были записаны, для бинарных сериализаторов такой такой порядок может быть и приемлем, но когда данные пишутся в обычный XML, такие ограничения смотрятся совсем дико. Может статься так, что данные будут генерироваться другими разработчиками, для начала можно будет объяснить, что порядок записи менять нельзя, в будущем это будет источник ошибок.
Для данной задачи вообще не нужно городить огород, если нет никаких требований к формату, то для начала можно всё писать в обычный CVS. А прочитать все строки до перевода строки из файла, распарсить данные по разделителям, конвертировать строки в данные, создать объект Person, инициализировать поля прочитанными данными и включить объект в вектор это задача нескольких десятков строк, буст здесь реально не нужен и вреден.
Вы в чем-то и правы, а в чем-то — нет.
Помимо технических деталей, которые сразу приходят в голову при попытке написания своего
сериализатора, — а это проблемы хранения std::string и std::wstring в одном архиве,
необходимость escape-последовательностей для текстового формата и другие, — есть еще внешние
факторы, которые оказывают влияние на выбор решения, и факторы весомые.
Во-первых, любой серъезный код — subject to change (предмет изменений), как мне нравится говорить.
Часто программист не в состоянии предвидеть, что случится с его классом Person, изначально
хранившим имя и возраст, а потом разросшимся до пятнадцати полей и восемнадцати методов.
И тогда у него, возможно, не останется выбора, кроме как использовать Boost.serialization, а
ведь это можно было сделать сразу, ничего не теряя. Замечу, что такая модернизация
может быть связана со значительными изменениями в клиентском коде.
Во-вторых, время и ресурсы тоже ограничены. На освоение упомянутой библиотеки уйдет часик-другой, а
приобретенные знания можно будет быстро применить в другой ситуации. Согласитесь, это гораздо
проще и эффективнее, чем снова писать нужную в данном конкретном случае реализацию, пусть даже
немного более прозрачную и безопасную.
Писать велосипед можно только тогда, когда ни одно из существующих решений не удовлетворяет в полной
мере условиям задачи или техническим требованиям, таким как скорость, например.
Вот тогда и имеет смысл засесть и поднапрячь мозги.
Здравствуйте, okman, Вы писали:
O>Используйте библиотеку сериализации из Boost, она так и называется — serialization. O>Пользоваться очень просто, достаточно определить метод serialize для нужного класса и O>использовать перегруженный метод &. Кстати, сериализация для контейнеров типа vector в O>Boost уже имеется.
Здравствуйте, Usefur, Вы писали:
U>Уважаемые, прошу вашей помощи. Меня интересует вопрос как записать данные из вектора (в моем случае "vector <Person> pers") данные в файл, чтобы потом их можно было считать. В векторе хранятся только данные о Имени, Фамилии, Дате рождения, Телефоне. Ну и нужно их сохранять, чтобы при каждом запуске программы не вводить всю информацию заново. Прочитал что лучше всего сохранять в бинарный файл, но как реализовать не знаю.Напишите пожалуйста код...
сдаётся мне что тут ищется помощь в "написании лабораторной работы", я угадал?
Для начала гугли (или копай МСДН) в поисках стандартных операций для работы с файлами, даю наводку:
1. fopen() — открытие файла, fprintf() — запись в файл, fscanf() — чтение из файла, fclose()-закрытие файла.
2. вариант продвинутее, класс fstream.
ну а потом подумай как тебе удобно упаковать данные в блоки чтоб их потом оттуда можно было однозначно вычитать.
Здравствуйте, okman, Вы писали:
O>Во-первых, любой серъезный код — subject to change (предмет изменений), как мне нравится говорить. O>Часто программист не в состоянии предвидеть, что случится с его классом Person, изначально O>хранившим имя и возраст, а потом разросшимся до пятнадцати полей и восемнадцати методов. O>И тогда у него, возможно, не останется выбора, кроме как использовать Boost.serialization, а O>ведь это можно было сделать сразу, ничего не теряя. Замечу, что такая модернизация O>может быть связана со значительными изменениями в клиентском коде.
И что будет с обратной совместимостью при использовании Boost.serialization, если, скажем, в коде вам потребовалось заменить std::list<Person> на std::vector<Person> ?
O>Во-вторых, время и ресурсы тоже ограничены. На освоение упомянутой библиотеки уйдет часик-другой, а O>приобретенные знания можно будет быстро применить в другой ситуации. Согласитесь, это гораздо O>проще и эффективнее, чем снова писать нужную в данном конкретном случае реализацию, пусть даже O>немного более прозрачную и безопасную.
А потом уйдут многие часы на борьбу с ошибками Boost.serialization.
O>Писать велосипед можно только тогда, когда ни одно из существующих решений не удовлетворяет в полной O>мере условиям задачи или техническим требованиям, таким как скорость, например. O>Вот тогда и имеет смысл засесть и поднапрячь мозги.
Велосипеды хороши тем, что свои ошибки ты всегда можешь исправить...
Здравствуйте, urukhai, Вы писали:
U>Здравствуйте, Usefur, Вы писали:
U>>Уважаемые, прошу вашей помощи. Меня интересует вопрос как записать данные из вектора (в моем случае "vector <Person> pers") данные в файл, чтобы потом их можно было считать. В векторе хранятся только данные о Имени, Фамилии, Дате рождения, Телефоне. Ну и нужно их сохранять, чтобы при каждом запуске программы не вводить всю информацию заново. Прочитал что лучше всего сохранять в бинарный файл, но как реализовать не знаю.Напишите пожалуйста код...
U>сдаётся мне что тут ищется помощь в "написании лабораторной работы", я угадал?
U>Для начала гугли (или копай МСДН) в поисках стандартных операций для работы с файлами, даю наводку: U>1. fopen() — открытие файла, fprintf() — запись в файл, fscanf() — чтение из файла, fclose()-закрытие файла. U>2. вариант продвинутее, класс fstream.
U>ну а потом подумай как тебе удобно упаковать данные в блоки чтоб их потом оттуда можно было однозначно вычитать.
Е нет...на курсовую(которую мне послезавтра сдавать))
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, okman, Вы писали:
O>>Во-первых, любой серъезный код — subject to change (предмет изменений), как мне нравится говорить. O>>Часто программист не в состоянии предвидеть, что случится с его классом Person, изначально O>>хранившим имя и возраст, а потом разросшимся до пятнадцати полей и восемнадцати методов. O>>И тогда у него, возможно, не останется выбора, кроме как использовать Boost.serialization, а O>>ведь это можно было сделать сразу, ничего не теряя. Замечу, что такая модернизация O>>может быть связана со значительными изменениями в клиентском коде.
BFE>И что будет с обратной совместимостью при использовании Boost.serialization, если, скажем, в коде вам потребовалось заменить std::list<Person> на std::vector<Person> ?
а что будет в собственноручно написанном велосипеде? шоколад?
O>>Во-вторых, время и ресурсы тоже ограничены. На освоение упомянутой библиотеки уйдет часик-другой, а O>>приобретенные знания можно будет быстро применить в другой ситуации. Согласитесь, это гораздо O>>проще и эффективнее, чем снова писать нужную в данном конкретном случае реализацию, пусть даже O>>немного более прозрачную и безопасную.
BFE>А потом уйдут многие часы на борьбу с ошибками Boost.serialization.
можно пример ошибки?
O>>Писать велосипед можно только тогда, когда ни одно из существующих решений не удовлетворяет в полной O>>мере условиям задачи или техническим требованиям, таким как скорость, например. O>>Вот тогда и имеет смысл засесть и поднапрячь мозги.
BFE>Велосипеды хороши тем, что свои ошибки ты всегда можешь исправить...
Здравствуйте, blackhearted, Вы писали: B>Здравствуйте, B0FEE664, Вы писали:
BFE>>И что будет с обратной совместимостью при использовании Boost.serialization, если, скажем, в коде вам потребовалось заменить std::list<Person> на std::vector<Person> ? B>а что будет в собственноручно написанном велосипеде? шоколад?
Да, если писать сериализацию объектов, а не типов.
O>>>Во-вторых, время и ресурсы тоже ограничены. На освоение упомянутой библиотеки уйдет часик-другой, а O>>>приобретенные знания можно будет быстро применить в другой ситуации. Согласитесь, это гораздо O>>>проще и эффективнее, чем снова писать нужную в данном конкретном случае реализацию, пусть даже O>>>немного более прозрачную и безопасную.
BFE>>А потом уйдут многие часы на борьбу с ошибками Boost.serialization. B>можно пример ошибки?
У нас те же самые проблемы.
BFE>>Велосипеды хороши тем, что свои ошибки ты всегда можешь исправить... B>а буст, типа, закрыт?
Вот возьмите буст, найдите тикет на ошибку в Boost.serialization для 1.42. И попробуйте её понять.
Я пробовал. Я знаю, насколько это не просто. Особенно в то время "радовали" комминтарии автора, типа "две недели провожу поиски ошибки — пока не нашёл"
Ладно, допустим я нашел ошибку и исправил. А дальше что ? Авторы, которые пишут в буст посчитают, что такое исправление в новой версии не нужно. Забъют на обратную совместимость под лозунгом: новая версия свободна от старых ошибок. Значит придётся использовать старую версию буста ? А у нас в проекте есть ещё и другие библиотеки, которые косвенно зависят от новой версии буста и со старой не совместимы. Значит при компиляции придётся использовать две разные версии буста ? Или локально патчит каждую новую версию?
Я таким путём решил не ходить. Я написал обходной код и использовал его некоторое время. Потом проект перешёл к другому человеку и он (вернее она) промучившись некоторое время с этим кодом написала по два разных способа сериализации для загрузки старых и новых версий файлов. К счастью для нашего проекта это удалось сделать, но так повезло не всем.
Открытость и закрытость сути не меняет. Зависимость от авторов библиотеки остаётся.
Здравствуйте, B0FEE664, Вы писали:
BFE>И что будет с обратной совместимостью при использовании Boost.serialization, если, скажем, в коде вам потребовалось заменить std::list<Person> на std::vector<Person> ?
Речь шла не об обратной совместимости, а о том, что широта классов и ситуаций, охватываемых
бустовской сериализацией, с лихвой покрывает большинство прикладных задач, чего не скажешь про
самописные решения, которые приходится дорабатывать "на ходу" и нередко перепроектировать
клиентский интерфейс. В приведенном Вами примере, скорее всего, почти ничего переделывать
не придется — для list в бусте уже определены функции сериализации, в Person тоже.
Так что, вероятно, дело может свестить к простой замене одного-двух заголовков.
O>>Во-вторых, время и ресурсы тоже ограничены. На освоение упомянутой библиотеки уйдет часик-другой, а O>>приобретенные знания можно будет быстро применить в другой ситуации. Согласитесь, это гораздо O>>проще и эффективнее, чем снова писать нужную в данном конкретном случае реализацию, пусть даже O>>немного более прозрачную и безопасную.
BFE>А потом уйдут многие часы на борьбу с ошибками Boost.serialization.
Это можно сказать про любую библиотеку. Все же разумнее доверять популярным решениям, которые
массово "обкатываются" и постоянно доводятся до ума.
Да, данный способ верен для POD-типов и хорош тем что не надо задумываться о внутреннем устройстве структуры/класса — единственное, что нужно использовать — массивы вместо указателей. Также, его можно легко расширить, добавив дополнительные данные в структуру и ничего не поломается(если нет необходимости в поддержке совместимости со старыми форматами файлов где хранится информация). В рамках поставленной задачи — самое разумное решение в 30-50 строк. Ну и что, что файл может стать большим — чем-то приходится жертвовать.
Раз кто-то усомнился в том что так можно(а минусов-то понаставили ) — привожу полный код решения.
Запись :
#include <fstream>
#include <vector>
using namespace std;
struct Person {
int age;
char fir_name[30];
char sec_name[30];
};
Person p = {20, "Martin", "Fowler"};
int main () {
vector<Person> pers;
pers.push_back(p);
pers.push_back(p);
ofstream out ("data.txt", ios::binary);
int size = pers.size();
out.write((char*)(&size), 4);
out.write((char*)&pers[0], pers.size()*sizeof(Person));
out.close();
}
Чтение :
#include <fstream>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
struct Person {
int age;
char fir_name[30];
char sec_name[30];
};
Person p;
int main () {
vector<Person> pers;
int size = 0;
ifstream in("data.txt", ios::binary);
in.read((char*)&size, 4);
pers.resize(size);
in.read((char*)&pers[0], size*sizeof(Person));
for_each(pers.begin(), pers.end(), [](Person p) -> int {
cout << "age-" << p.age << endl;
cout << "fir_name-" << p.fir_name << endl;
cout << "sec_name-" << p.sec_name << endl
});
in.close();
}