Search code examples
c++filealignment

Writing aligned data in binary file


I am creating a file with some data objects inside. data object have different sizes and are something like this (very simplified):

struct Data{
   uint64_t size;
   char     blob[MAX_SIZE];
// ... methods here:
}

At some later step, the file will be mmap() in memory, so I want the beginning of every data objects to starts on memory address aligned by 8 bytes where uint64_t size will be stored (let's ignore endianness).

Code looks more or less to this (currently hardcoded 8 bytes):

size_t calcAlign(size_t const value, size_t const align_size){
    return align_size - value % align_size;
}

template<class ITERATOR>
void process(std::ofstream &file_data, ITERATOR begin, ITERATOR end){
    for(auto it = begin; it != end; ++it){
        const auto &data = *it;

        size_t bytesWriten = data.writeToFile(file_data);

        size_t const alignToBeAdded = calcAlign(bytesWriten, 8);

        if (alignToBeAdded != 8){
            uint64_t const placeholder = 0;

            file_data.write( (const char *) & placeholder, (std::streamsize) alignToBeAdded);
        }
    }
}

Is this the best way to achieve alignment inside a file?


Solution

  • you don't need to rely on writeToFile to return the size, you can use ofstream::tellp

    const auto beginPos = file_data.tellp();
    // write stuff to file
    const auto alignSize = (file_data.tellp()-beginPos)%8;
    if(alignSize)
        file_data.write("\0\0\0\0\0\0\0\0",8-alignSize);
    

    EDIT post OP comment: Tested on a minimal example and it works.

    #include <iostream>
    #include <fstream>
    int main(){
        using namespace std;
        ofstream file_data;
        file_data.open("tempfile.dat", ios::out | ios::binary);
        const auto beginPos = file_data.tellp();
        file_data.write("something", 9);
        const auto alignSize = (file_data.tellp() - beginPos) % 8;
        if (alignSize)
            file_data.write("\0\0\0\0\0\0\0\0", 8 - alignSize);
        file_data.close();
        return 0;
    }