In C++, to serialize simple data, aka plain old data (POD), where the layout in memory is predictable, you can use a char*
(byte) buffer:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Serialization for simple data structures (POD) with C++ | |
// Şamil Korkmaz, 16.12.2024 | |
#include <iostream> | |
#include <cstring> // For memcpy | |
// Simple POD structure | |
struct MyStruct { | |
int id; | |
double value; | |
char name[50]; | |
}; | |
void serializeToBuffer(const MyStruct& obj, char* buffer) { | |
std::memcpy(buffer, &obj, sizeof(MyStruct)); | |
} | |
void deserializeFromBuffer(const char* buffer, MyStruct& obj) { | |
std::memcpy(&obj, buffer, sizeof(MyStruct)); | |
} | |
int main() { | |
MyStruct original = {42, 3.14, "Example"}; | |
char buffer[sizeof(MyStruct)]; | |
serializeToBuffer(original, buffer); | |
MyStruct deserialized; | |
deserializeFromBuffer(buffer, deserialized); | |
// Output the deserialized structure | |
std::cout << "Deserialized Object:\n"; | |
std::cout << "ID: " << deserialized.id << "\n"; | |
std::cout << "Value: " << deserialized.value << "\n"; | |
std::cout << "Name: " << deserialized.name << "\n"; | |
return 0; | |
} |
This method cannot be used for non-POD types (e.g., those with pointers or virtual methods) because their memory layout is not portable. Examples are std::string, std::vector. For such types, you can use std::ostringstream
:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Serialization for non-POD (e.g. std::string, std::vector) with C++ | |
// Şamil Korkmaz, 16.12.2024 | |
#include <sstream> // Required for std::ostringstream and std::istringstream | |
#include <iostream> | |
#include <vector> | |
#include <string> | |
#include <cstring> // For memcpy | |
struct MyStruct { | |
int id; | |
double value; | |
std::string name; | |
std::vector<int> numbers; | |
void serialize(std::ostream& out) const { | |
out.write(reinterpret_cast<const char*>(&id), sizeof(id)); | |
out.write(reinterpret_cast<const char*>(&value), sizeof(value)); | |
// Serialize std::string: First the string size, followed by the characters | |
size_t nameSize = name.size(); | |
out.write(reinterpret_cast<const char*>(&nameSize), sizeof(nameSize)); | |
out.write(name.data(), nameSize); | |
// Serialize std::vector: First the vector size, followed by its elements | |
size_t vecSize = numbers.size(); | |
out.write(reinterpret_cast<const char*>(&vecSize), sizeof(vecSize)); | |
out.write(reinterpret_cast<const char*>(numbers.data()), vecSize * sizeof(int)); | |
} | |
void deserialize(std::istream& in) { | |
in.read(reinterpret_cast<char*>(&id), sizeof(id)); | |
in.read(reinterpret_cast<char*>(&value), sizeof(value)); | |
// Deserialize std::string: Resize the string and read the characters into it | |
size_t nameSize; | |
in.read(reinterpret_cast<char*>(&nameSize), sizeof(nameSize)); | |
name.resize(nameSize); | |
in.read(&name[0], nameSize); | |
// Deserialize std::vector: Resize the vector and read its elements | |
size_t vecSize; | |
in.read(reinterpret_cast<char*>(&vecSize), sizeof(vecSize)); | |
numbers.resize(vecSize); | |
in.read(reinterpret_cast<char*>(numbers.data()), vecSize * sizeof(int)); | |
} | |
}; | |
int main() { | |
MyStruct original = {42, 3.14, "Example", {1, 2, 3, 4, 5}}; | |
std::ostringstream out; // Ensure <sstream> is included | |
original.serialize(out); | |
std::istringstream in(out.str()); // Ensure <sstream> is included | |
MyStruct deserialized; | |
deserialized.deserialize(in); | |
std::cout << "Deserialized Object:\n"; | |
std::cout << "ID: " << deserialized.id << "\n"; | |
std::cout << "Value: " << deserialized.value << "\n"; | |
std::cout << "Name: " << deserialized.name << "\n"; | |
std::cout << "Numbers: "; | |
for (int num : deserialized.numbers) { | |
std::cout << num << " "; | |
} | |
std::cout << "\n"; | |
return 0; | |
} |
No comments:
Post a Comment