CodeBlanks Logo Icon CodeBlanks

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.

Practice 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;.

Starter code

main.cpp
#include <iostream>
#include <fstream>

// Write version and value to binary, read back and check the version

int main() {
    // Add write, read and version check
    return 0;
}

Sample solution

main.cpp
#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;
}

Expected output

v1: 42

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Match each piece to its role

Term Meaning
int version = 1 Version number
if (version == 1) Version check
version = 2 New format
migration Migrates old data

2 Why is a version number written?

  • To shrink the file
  • To color the output
  • To speed up compilation
  • For backward compatibility Correct answer

Explanation: The version number lets new programs read old files.

3 Complete the version variable

Question
int ____ = 1;
Answer
int version = 1;

Explanation: int version = 1; sets the version number.

All lessons in Advanced