Векторная сериализация
Я пытаюсь двоично сериализовать данные вектора. В этом примере ниже я сериализую в строку, а затем десериализую обратно в вектор, но не получаю те же данные, с которых я начал. Почему это так?
vector<size_t> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
string s((char*)(&v[0]), 3 * sizeof(size_t));
vector<size_t> w(3);
strncpy((char*)(&w[0]), s.c_str(), 3 * sizeof(size_t));
for (size_t i = 0; i < w.size(); ++i) {
cout << w[i] << endl;
}
Я ожидаю получить выход
1
2
3
но вместо этого получить выход
1
0
0
(на gcc-4.5.1)
4 ответа
Ошибка в вызове strncpy
, Со связанной страницы:
Если длина src меньше n, strncpy () дополняет остаток dest нулевыми байтами.
Итак, после первого 0
байт в сериализованных данных находится остаток w
массив данных дополняется 0
s.
Чтобы это исправить, используйте for
петля или std::copy
std::copy( &s[0],
&s[0] + v.size() * sizeof(size_t),
reinterpret_cast<char *>(w.data()) );
ИМО вместо использования std::string
в качестве буфера, просто используйте char
массив для хранения сериализованных данных.
Пример на идеоне
strncpy
гигантская куча неудач. Это закончится рано на вашем входе, потому что size_t
иметь несколько нулевых байтов, которые он интерпретирует как терминатор NULL, оставляя их как построенные по умолчанию 0. Если вы выполнили этот тест на машине BE, все было бы 0. Используйте std::copy
,
Самым безопасным способом было бы просто перебрать вектор и сохранить значения по отдельности в массиве символов размера 3*sizeof(size_t). Таким образом, вы не зависите от внутренней структуры реализации векторного класса.
Чтобы сериализовать этот вектор в строку. Сначала необходимо преобразовать каждый элемент этого вектора из целого числа в строку, содержащую то же представление ascii этого числа, эту операцию можно назвать сериализацией целого числа в строку.
Так, например, предполагая, что целое число составляет 10 цифр, мы можем
// create temporary string to hold each element
char intAsString[10 + 1];
затем преобразовать целое число в строку
sprintf(intAsString, "%d", v[0]);
или же
itoa( v[0], intAsString, 10 /*decimal number*/ );
Вы также можете использовать ostringstream и оператор <<
если вы посмотрите на содержимое памяти intAsString и v[0], они сильно различаются, первая содержит буквы ascii, которые представляют значение v [0] в десятичной системе счисления (основание 10), тогда как v [0] содержит двоичное представление числа (потому что так компьютеры хранят числа).