Форум программистов, компьютерный форум CyberForum.ru

Сериализация - C++

Восстановить пароль Регистрация
 
FarStar
Заблокирован
14.03.2013, 21:41     Сериализация #1
Не создаётся тема

Добавлено через 11 секунд
Привет! Вот код, который записывает в динарник структуру и считывает её оттуда, конечно же вектор считывается не корректно, точнее в считанном векторе тоже две ячейки, но в них бред А хотелось бы халявы, чтоб отдельно вектор не строково не хреначить.... Может есть идеи или вектора так просто не запихнуть в бинарник?
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
struct cool
    {
        int a;
        std::string str;
        std::vector<std::string> vec;
    };
    cool c;
    c.a=34;
    c.str="PREVED";
    c.vec.push_back("ONE");
    c.vec.push_back("TWO");
    size_t size=sizeof(c);
    std::fstream fs("save.dat",std::ios::out | std::ios::binary);
    fs.write((char*)&size,sizeof(size_t));
    fs.write((char*)&c,size);
    fs.close();
 
    cool c1;
    std::fstream fs1("save.dat",std::ios::in | std::ios::binary);
    size_t size1;
    fs1.read((char*)&size1,sizeof(size_t));
    fs1.read((char*)&c1,size1);
    fs1.close();
    std::cout << c1.a << " " << c1.str << " " << c1.vec[0] << " " << c1.vec[1] << std::endl;
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.03.2013, 21:41     Сериализация
Посмотрите здесь:

Сериализация C++
Сериализация данных C++
C++ сериализация
Сериализация C++
C++ Потоки, сериализация
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
14.03.2013, 22:09     Сериализация #2
таким макаром можно только POD типы сериализовывать\десериализовывать.
строки и вектора к ним не относятся. чтобы понять почему, нарисуем себе такой класс, в котором есть указатель на что-то (в строках и векторах присутствует подобный указатель). Ну будем придираться к отсутствию всяких правильных конструкторов копирования и операторов = и прочих деталей, которые к сути сейчас не имеют отношения
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
class Foo
{
   int* m_ptr;
 
public:
   Foo()
    : m_ptr(new int(666));
   {
   }
 
   ~Foo()
   {
       delete m_ptr;
   }
};
 
sizeof(Foo) >= sizeof(int*);
 
где-то в коде:
{
  Foo foo;
  // внутри foo под указатель была выделена память. в нее записали 666
  // пусть этот указатель указывает на ячейку c адресом 0xf0f0f0f0;
  // тут сериализация как у вас:
  stream.write(&foo, sizeof(foo));
  //т.е. тут в стрим записались как минимум 4 байта. значение 0xf0f0f0f0
  //далее происходит выход из области видимости, вызывается деструктор foo,
  //память по адресу 0xf0f0f0f0 освобождается и ее больше использовать нельзя.
}
 
{
   // В другом месте хотим десериализовать.
   Foo foo;
   // Вот тут снова внутри foo выделяется память и m_ptr указывает на ячейку 0xa0a0a0a0;
   // А тут мы десериализовываем:
   stream.read(&foo, sizeof(foo));
   // Что тут происходит. Тут перезаписываются все внутренние поля foo. В нашем случае  у нас только
   // указатель который до десериализации указывал на правильно выделенную память 0xa0a0a0a0,
   // а после десериализации будет указывать на 0xf0f0f0f0, которая уже была удалена и в которой
   // может быть всякий хлам или которую уже заюзал кто-то другой. Т.е. имеем проблему.
}
При такой сериализации не сохраняется значение 666, как можно было бы подумать. Сохраняется адрес ячейки, где хранится это число 666 и в какой-то момент этот адрес становится недействительным.
Поэтому для таких классов нужно писать специальные функции сериализации/десериализации.
FarStar
Заблокирован
14.03.2013, 22:39  [ТС]     Сериализация #3
Ну всё понятно, тоесть чтоб записать какой - то жалкий стринг, надо обязательно писать ещё и его длинну....Тость дополнительные 4 байта , а если строк - миллиард ? Итить расколотить....
Так получается? Как же хреново, что в STL нет встроенного сериализатора....
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
td::fstream fs("save.dat",std::ios::out | std::ios::binary);
    std::string str="Die you son of a bitch! -=Duke Nukem=-";
    size_t len=str.length();
    fs.write((char*)&len,sizeof(size_t));
    fs.write(str.c_str(),len);
    fs.write((char*)&c,size);
    fs.close();
    //дальше типа читаю ))
    fs.open("save.dat",std::ios::in | std::ios::binary);
    size_t fucked_len;
    fs.read((char*)&fucked_len,sizeof(size_t));
    char* buf=new char[fucked_len];
    fs.read((char*)&buf,fucked_len);
    std::string token=buf;
    fs.close();
А может есть какие - то методы что ли выравнивания данных в бинарнике или какие - то приёмы для: а) уменьшения объёма, б) увеличения скорости считывания его потом? Может какие - то фишки типа #pragma pack ?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
14.03.2013, 22:56     Сериализация #4
есть специальные стримы, котрые пакуют все, что в них пишут. но это в худшую сторону повлияет на скорость чтения\записи. прагмы тут никак не помогут. Сериализация миллиардов строк - нестандартная задача. Стандартная библиотека рассчитана на какие-то общие случаи. В ситуациях, сильно отклоняющихся от общих нужно спец решения применять. И их нужно поискать.
FarStar
Заблокирован
14.03.2013, 23:04  [ТС]     Сериализация #5

Не по теме:

Почему все пишут названия классов в примерах Foo , типа Фуу.. ))) Плохо пахнет вокруг или это из какой - то стандартной книжки привычка


А вот, к примеру, какие могут быть рекомендации для увеличения скорости чтения бинарника (скорость записи меня не интересует), который формирует, например, такой структурой:
C++
1
2
3
4
5
6
struct Item
    {
        size_t id;
        std::string name;
        std::vector<std::string> cells;
    };
с учётом того, что в файле таких структур должно быть около триллиона?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
14.03.2013, 23:50     Сериализация #6
триллион? это типа террабайт, если струтурка занимала один байт. не много ли? а файловас система такие
размеры файлов поддерживает? даже если поддержывает, для таких случаев файлы не подходят. есть базы данных и всякие другие решения. сохранять такой объем данных в один файл - это бред.
FarStar
Заблокирован
15.03.2013, 09:59  [ТС]     Сериализация #7
Цитата Сообщение от DU Посмотреть сообщение
это типа террабайт
А ты что не видел хардисков на терабайт? А на два? А на 10 ? NTFS поддерживает максимальный размер файла до 16 терабайт, а теоретический даже больше. А что по - твоему, база данных не на хард диске хранится ?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.10.2013, 18:11     Сериализация
Еще ссылки по теме:

C++ Сериализация и десериализация двусвязного списка
C++ Сериализация
C++ Сериализация массива int

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

Или воспользуйтесь поиском по форуму:
Kranggg
0 / 0 / 0
Регистрация: 16.07.2013
Сообщений: 4
21.10.2013, 18:11     Сериализация #8
Цитата Сообщение от FarStar Посмотреть сообщение

Не по теме:

Почему все пишут названия классов в примерах Foo , типа Фуу.. ))) Плохо пахнет вокруг или это из какой - то стандартной книжки привычка


А вот, к примеру, какие могут быть рекомендации для увеличения скорости чтения бинарника (скорость записи меня не интересует), который формирует, например, такой структурой:
C++
1
2
3
4
5
6
struct Item
    {
        size_t id;
        std::string name;
        std::vector<std::string> cells;
    };
с учётом того, что в файле таких структур должно быть около триллиона?
удалось как-то решить проблему скорости записи/чтения?
Yandex
Объявления
21.10.2013, 18:11     Сериализация
Ответ Создать тему
Опции темы

Текущее время: 09:00. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru