Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Reading and Writing std::vector<struct> to a file

I need to write a vector to a file, and then read it back into a vector.

The vector contains hundreds, possibly thousands, of structs which each contain 2 different structs.

I thought that the best way to do it would be to get the pointer with MyVector.data() and somehow write the data using that.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Just in case here’s a diagram of the vector:

MyVector
    - Struct 1
        - Struct A
            - float
            - float
            - bool
            ...
        - Struct B
            - float
            - float
            - bool
            ...
    - Struct 2
        - Struct A
            - float
            - float
            - bool
            ...
        - Struct B
            - float
            - float
            - bool
            ...

and so on.

I tried multiple methods, such as ofstream.write() and fwrite(), but none of them worked.

void PosBot::SaveMacro(std::string macroName) {
    int val = _mkdir("PosBot");

    std::string a = "PosBot/" + macroName + ".pbor";
    std::ofstream outfile(a.c_str(), std::ios_base::binary);
    std::copy(Frames.begin(), Frames.end(), std::ostreambuf_iterator<char>(outfile));
    outfile.close();
}

void PosBot::LoadMacro(std::string macroName) {
    Frames.clear();
    Checkpoints.clear();
    CheckpointFrames.clear();
    std::string a = "PosBot/" + macroName + ".pbor";
    std::ifstream infile(a.c_str(), std::ios_base::binary);
    std::istreambuf_iterator<char> iter(infile);
    std::copy(iter, std::istreambuf_iterator<char>(), std::back_inserter(Frames)); // this leaves newVector empty
    infile.close();
}

This gives me an error of:

binary ‘=’: no operator found which takes a right-hand operand of type ‘Frame’ (or there is no acceptable conversion)

>Solution :

std::ostreambuf_iterator writes character data to the output stream whenever it is assigned a single character via its operator=. Since you are specifying char as the CharT template parameter of std::ostreambuf_iterator, its operator= expects a char value to be assigned to it (ie, when used to write data from a std::vector<char>, std::string, etc), but you are trying to write Frame objects from a std::vector<Frame> instead. IOW, since you are trying to write Frame objects where char values are expected, that is why you are getting the conversion error on operator=.

You have a similar issue with reading in using std::istreambuf_iterator, too. It is meant for reading in character data (via its operator*), not structured data.

For what you are attempting to do, you need to use std::ostream_iterator (and std::istream_iterator) instead. You will simply have to define an overloaded operator<< (and operator>>) for Frame to write/read its member data to/from a std::ostream/std::istream as needed.

Try this:

std::ostream& operator<<(std::ostream& out, const Frame &frame) {
    // write Frame data to ostream as needed.  If Frame is a POD type,
    // you can write the whole thing in one go, eg...
    return out.write(reinterpret_cast<const char*>(&frame), sizeof(frame));

    // but, if Frame is not a POD type, you will have to write out
    // each data member individually instead...
}

std::istream& operator>>(std::istream& in, Frame &frame) {
    // read Frame data from istream as needed.  If Frame is a POD type,
    // you can read the whole thing in one go, eg...
    return in.read(reinterpret_cast<char*>(&frame), sizeof(frame));

    // but, if Frame is not a POD type, you will have to read in
    // each data member individually instead...
}

void PosBot::SaveMacro(std::string macroName) {
    int val = _mkdir("PosBot");

    std::string a = "PosBot/" + macroName + ".pbor";
    std::ofstream outfile(a.c_str(), std::ios_base::binary);
    std::copy(Frames.begin(), Frames.end(), std::ostream_iterator<Frame>(outfile));
    outfile.close();
}

void PosBot::LoadMacro(std::string macroName) {
    Frames.clear();
    Checkpoints.clear();
    CheckpointFrames.clear();
    std::string a = "PosBot/" + macroName + ".pbor";
    std::ifstream infile(a.c_str(), std::ios_base::binary);
    std::istream_iterator<Frame> iter(infile);
    std::copy(iter, std::istream_iterator<Frame>(), std::back_inserter(Frames));
    infile.close();
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading