Search code examples
c++stdoutfstream

Writing/reading strings as binary into random accessed file


Simple question: I want to write strings of fixed length into a binary file (that is, as binary), as illustrated in the following snippet.

The writing "looks" fine, but reading from the file doesn't work (compiles and runs without crashed, but doesn't give the expected result).

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    {
        std::ofstream out {"out.dat", std::ios::binary};

        //all of length 5
        std::string a[] {{"12345"}, {"6789A"}, {"BCDEF"}};

        //write down strings without \0
        out.write(a[0].c_str(), a[0].length());
        out.write(a[1].c_str(), a[1].length());
        out.write(a[2].c_str(), a[2].length());
    }

    {
        std::ifstream in {"out.dat", std::ios::binary};

        std::string s2 {5, '\0'}; //I can store at least 5 chars
        in.seekg(0 + 2 * 5); //try to read string of index 2
        in.read(&s2[0], 5);

        std::cout << s2 << std::endl; //prints "BC", not "BCDEF"  
    }
}

The last line should recover the string "BCDEF", but only "BC" is printed (g++ 10.2.0).

Since the strings have fixed lengths, and that I write that specified number of bytes (chars) into the file, I should be able to recover them with seekg (that is, I know where they start, and I can set the input position indicator right there to read).

Note that I don't this this is a duplicate of this question, since I'm writing chars directly (I don't need to reinterpret_cast them).


Solution

  • This uses the constructor that takes an std::initializer_list:

    std::string s2 {5, '\0'};
    

    ... and creates a string with 2 characters with the values 5 and 0 (or whatever \0 is).

    It should be std::string s2 (5, '\0');

    Example:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    
    int main()
    {
        {
            std::ofstream out {"out.dat", std::ios::binary};
    
            //all of length 5
            std::vector<std::string> a{{"12345"}, {"6789A"}, {"BCDEF"}};
    
            //write down strings without \0
            for(auto& s : a)
                out.write(s.c_str(), s.size());
        }
    
        {
            std::ifstream in {"out.dat", std::ios::binary};
    
            std::string s2(5,'\0'); //I can store at least 5 chars
            in.seekg(0 + 2 * 5); //try to read string of index 2
            in.read(s2.data(), 5);
    
            std::cout << s2 << std::endl; //prints "BC", not "BCDEF"  
        }
    }
    

    `