2

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).

0

1 Answer 1

4

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"  
    }
}

`

Sign up to request clarification or add additional context in comments.

3 Comments

I am... ashamed. It was so simple, and so unrelated to what I tought the problem was... Thanks
@R.Absil You're welcome! No need to feel ashamed - I had to look at it twice myself. :-)
Thanks, just did that, with some older questions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.