C++
Versioning
Learn serialization versioning and compatibility.
What is versioning?
Versioning adds a version number to serialized data to ensure future compatibility. When the data format changes, the version is checked on read and a data migration is applied if needed.
Example: you first write int version = 1; to the file, then the actual data. On read you first read the version and use if (version == 1) to read in that format. Later you can change the format and set version = 2; old files can still be read through the version == 1 branch. This gives backward compatibility.
Version check and migration
On read you first read the version number. Then you write a separate read branch for each version with if / else if. When you add a new version, you keep the old branch and add a new one.
Example: if (version == 1) { ifs.read(...); } and else if (version == 2) { ifs.read(...); /* new field */ }. Version 1 files read from the first branch, version 2 from the second. This way both old and new files work with the same program. Migration is the logic of converting old data to the new format; it happens inside these branches.
Exercise Write and read a versioned binary file
Write two blocks. In the first block define int version = 1; and int value = 42;, open std::ofstream ofs("data.bin", std::ios::binary) and write both with ofs.write. In the second block define int version = 0; int value = 0;, open std::ifstream ifs("data.bin", std::ios::binary) and read both with ifs.read. With if (version == 1) print std::cout << "v1: " << value;.
Show example solution
#include <iostream>
#include <fstream>
int main() {
{
int version = 1;
int value = 42;
std::ofstream ofs("data.bin", std::ios::binary);
ofs.write(reinterpret_cast<const char*>(&version), sizeof(version));
ofs.write(reinterpret_cast<const char*>(&value), sizeof(value));
}
{
int version = 0;
int value = 0;
std::ifstream ifs("data.bin", std::ios::binary);
ifs.read(reinterpret_cast<char*>(&version), sizeof(version));
ifs.read(reinterpret_cast<char*>(&value), sizeof(value));
if (version == 1) {
std::cout << "v1: " << value;
}
}
return 0;
}
Test yourself
-
Match each piece to its role
- int version = 1
- Version number
- if (version == 1)
- Version check
- version = 2
- New format
- migration
- Migrates old data
-
Why is a version number written?
- To shrink the file
- To color the output
- To speed up compilation
- For backward compatibility
Show answer
For backward compatibility — The version number lets new programs read old files.
-
Complete the version variable
int ____ = 1;
Show answer
int version = 1;
Next lesson: Custom serialization