2016-07-21 2 views
0

Я хочу сохранить пример ниже на жестком диске в виде простого двоичного файла. Но вокруг сети я не нашел простого и чистого примера, как это сделать, поэтому я задаю вопрос:Хранить boost :: serialization :: serialize'ble struct как двоичный файл на жесткий диск

Как изменить код ниже, чтобы сохранить структуру как двоичный файл в двоичном файле?

#include <vector> 
#include <string> 
#include <bitset> 
#include <boost/serialization/string.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/bitset.hpp> 

template<size_t N> 
struct Example 
{ 
    std::string id; 
    std::vector<std::bitset<N>> bits; 
}; 

template<size_t N> 
Example<N> make_example() 
{ 
    Example<N> example; 

    example.id = "some id"; 

    example.bits.resize(100); 
} 

namespace boost 
{ 
    namespace serialization 
    { 
    template<typename Archive, size_t N> 
    void serialize (Archive & a 
        , Example<N> & e 
        , const unsigned int version) 
    { 
     a & e.id; 
     a & e.bits; 
    } 
    } 
} 

int main() 
{ 
    auto example = make_example<256>(); 

    std::ofstream ofs("filename", std::ios::binary); 

    boost::archive::binary_oarchive oa(ofs); 

    oa << example; // shouldn't use << as oa writes a text archive 
} 

ответ

2

Я считаю, что вопросы:

  1. Необходимость вернуть example в make_example(). Вероятно, вы получаете предупреждение о компиляторе, которое вы проигнорировали.
  2. Необходимо, чтобы #include <boost/archive/binary_oarchive.hpp>. В противном случае он даже не должен компилироваться.

Кроме того, ваш комментарий // shouldn't use << as oa writes a text archive не совсем правильно, потому что << теперь перегружен boost::archive::binary_oarchive так, что потоковое двоичную.

Таким образом, модифицированный код должен выглядеть следующим образом:

#include <vector> 
#include <string> 
#include <bitset> 
#include <fstream> 
#include <boost/serialization/string.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/bitset.hpp> 
// ADD THIS!!! 
#include <boost/archive/binary_oarchive.hpp> 

template<size_t N> 
struct Example 
{ 
    std::string id; 
    std::vector<std::bitset<N>> bits; 
}; 

template<size_t N> 
Example<N> make_example() 
{ 
    Example<N> example; 

    example.id = "some id"; 

    example.bits.resize(100); 
    // ADD THIS!!! 
    return(example); 
} 

namespace boost 
{ 
    namespace serialization 
    { 
    template<typename Archive, size_t N> 
    void serialize (Archive & a 
        , Example<N> & e 
        , const unsigned int version) 
    { 
     a & e.id; 
     a & e.bits; 
    } 
    } 
} 

int main() 
{ 
    auto example = make_example<256>(); 

    std::ofstream ofs("filename", std::ios::binary); 

    boost::archive::binary_oarchive oa(ofs); 

    oa << example; 

    return(0); 
} 

соответствующий пример на ТАК here.


Update Для того, чтобы сделать бинарную сериализацию std::bitset более компактной

Посмотрите на SO ответ на @ 6502 here. Вам будет нужно:

  1. Разделите serialize функцию на отдельные load и save функций. См. this (в разделе «Учебник :: Разделение сериализации в save/load»).
  2. В save, перебрать e.bits и использовать @bitset_to_bytes функции 6502, чтобы преобразовать КАЖДЫЙ из e.bits[i] в std::vector<unsigned char>. Затем вы получите std::vector<std::vector<unsigned char>> (локальная переменная в функции save). Сериализуйте это.
  3. И наоборот, в load, несериализуем, чтобы получить std::vector<std::vector<unsigned char>> (опять же, локальная переменная в load). Затем перейдите по этой коллекции и используйте функцию bitset_from_bytes<N> @ 6502 для преобразования EACHstd::vector<unsigned char> в e.bits[i].
  4. Удалить #include <boost/serialization/bitset.hpp>, вам больше не нужно.

Это должно привести хранение каждого std::bitset<N> от N до (N+7)/8 байтов в бинарном архиве.

Надеюсь, это поможет.

+0

Действительно, у меня были некоторые ошибки копирования/вставки в моем предыдущем сообщении. Я отредактировал так, как вы предложили.Когда я запускаю программу, genereated file _filename_ показывает текстовое содержимое, подобное этому (~ 25600 символов, как ожидалось): '^ @^D^H^D^H^A^@^@^@^@^@^@^@^@^G^@^@^@^@^@^@^@ некоторые id^@^@^@^@^@ d^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@ 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000^@^A^@^@^@^@^@^@ 0' – user1587451

+0

Итак, это работает, но все же это не ожидаемый результат. Размер файла составляет около 26K, но 256 * 100bit = 3200 байт = 3,125K. Размер файла ~ 8 раз больше, как ожидалось. – user1587451

+1

@ user1587451 действительно, но это двоичный архив. Перейдите в text_oarchive и включите соответствующий заголовок, чтобы увидеть разницу. Разница будет незначительной для вашего случая из-за битов, но с текстовым архивом будет больше текстовых метаданных. – aichao

Смежные вопросы