Binary serialization involves writing data in a binary format instead of a human-readable format, which is more efficient in terms of both space and speed.
#include <fstream>
class Person {
public:
std::string name;
int age;
Person() : name(""), age(0) {}
Person(const std::string& name, int age) : name(name), age(age) {}
// Serialize the object to binary format
void serialize(std::ofstream& outFile) const {
size_t nameLen = name.size();
outFile.write(reinterpret_cast<const char*>(&nameLen), sizeof(nameLen));
outFile.write(name.c_str(), nameLen);
outFile.write(reinterpret_cast<const char*>(&age), sizeof(age));
}
// Deserialize the object from binary format
void deserialize(std::ifstream& inFile) {
size_t nameLen;
inFile.read(reinterpret_cast<char*>(&nameLen), sizeof(nameLen));
name.resize(nameLen);
inFile.read(&name[0], nameLen);
inFile.read(reinterpret_cast<char*>(&age), sizeof(age));
}
};
int main() {
Person p1("Jane Doe", 25);
// Serialize to binary file
std::ofstream outFile("person.bin", std::ios::binary);
if (outFile.is_open()) {
p1.serialize(outFile);
outFile.close();
}
Person p2;
// Deserialize from binary file
std::ifstream inFile("person.bin", std::ios::binary);
if (inFile.is_open()) {
p2.deserialize(inFile);
inFile.close();
}
std::cout << "Deserialized Person: " << p2.name << " " << p2.age << std::endl;
return 0;
}
Proper error handling ensures the robustness of the serialization process.
#include <iostream>
#include <fstream>
int main() {
Person p1("Jane Doe", 25);
// Serialize with error handling
std::ofstream outFile("person.bin", std::ios::binary);
if (!outFile) {
std::cerr << "Error opening file for writing" << std::endl;
return 1;
}
p1.serialize(outFile);
outFile.close();
Person p2;
// Deserialize with error handling
std::ifstream inFile("person.bin", std::ios::binary);
if (!inFile) {
std::cerr << "Error opening file for reading" << std::endl;
return 1;
}
p2.deserialize(inFile);
if (inFile.fail()) {
std::cerr << "Error reading from file" << std::endl;
return 1;
}
inFile.close();
std::cout << "Deserialized Person: " << p2.name << " " << p2.age << std::endl;
return 0;
}
When dealing with complex objects, ensure all members, including pointers and nested objects, are correctly serialized.
#include <vector>
class Person {
public:
std::string name;
int age;
std::vector<int> scores;
// Serialization
void serialize(std::ofstream& outFile) const {
size_t nameLen = name.size();
outFile.write(reinterpret_cast<const char*>(&nameLen), sizeof(nameLen));
outFile.write(name.c_str(), nameLen);
outFile.write(reinterpret_cast<const char*>(&age), sizeof(age));
size_t scoresSize = scores.size();
outFile.write(reinterpret_cast<const char*>(&scoresSize), sizeof(scoresSize));
outFile.write(reinterpret_cast<const char*>(scores.data()), scoresSize * sizeof(int));
}
// Deserialization
void deserialize(std::ifstream& inFile) {
size_t nameLen;
inFile.read(reinterpret_cast<char*>(&nameLen), sizeof(nameLen));
name.resize(nameLen);
inFile.read(&name[0], nameLen);
inFile.read(reinterpret_cast<char*>(&age), sizeof(age));
size_t scoresSize;
inFile.read(reinterpret_cast<char*>(&scoresSize), sizeof(scoresSize));
scores.resize(scoresSize);
inFile.read(reinterpret_cast<char*>(scores.data()), scoresSize * sizeof(int));
}
};
Using libraries for JSON or XML serialization can simplify handling complex data formats and provide better interoperability.
Handling versioning requires maintaining backward compatibility when class definitions change over time.
class Person {
public:
std::string name;
int age;
std::string address; // Added in a new version
// Serialization with versioning
void serialize(std::ofstream& outFile) const {
int version = 2; // Version number
outFile.write(reinterpret_cast<const char*>(&version), sizeof(version));
size_t nameLen = name.size();
outFile.write(reinterpret_cast<const char*>(&nameLen), sizeof(nameLen));
outFile.write(name.c_str(), nameLen);
outFile.write(reinterpret_cast<const char*>(&age), sizeof(age));
// Serialize new field
size_t addressLen = address.size();
outFile.write(reinterpret_cast<const char*>(&addressLen), sizeof(addressLen));
outFile.write(address.c_str(), addressLen);
}
// Deserialization with versioning
void deserialize(std::ifstream& inFile) {
int version;
inFile.read(reinterpret_cast<char*>(&version), sizeof(version));
size_t nameLen;
inFile.read(reinterpret_cast<char*>(&nameLen), sizeof(nameLen));
name.resize(nameLen);
inFile.read(&name[0], nameLen);
inFile.read(reinterpret_cast<char*>(&age), sizeof(age));
if (version >= 2) {
// Deserialize new field
size_t addressLen;
inFile.read(reinterpret_cast<char*>(&addressLen), sizeof(addressLen));
address.resize(addressLen);
inFile.read(&address[0], addressLen);
}
}
};