ali kiani
ali kiani

Reputation: 887

write vector<vector<float>> to binary file

i need to save vector of vector to file and read them i try to this with this code but error occur:

void saveVector(std::string path, vector<vector<float>> myVector)
{
    std::ofstream FILE(path, std::ios::out | std::ofstream::binary);
    std::copy(myVector.begin(), myVector.end(), std::ostreambuf_iterator<char>(FILE));
    FILE.close();
}

error :

Error   C2679   binary '<<': no operator found which takes a right-hand operand of type 'std::vector<float,std::allocator<_Ty>>' (or there is no acceptable conversion)

Upvotes: 1

Views: 4662

Answers (2)

marcinj
marcinj

Reputation: 50036

In this line:

std::copy(myVector.begin(), myVector.end(), std::ostreambuf_iterator<char>(FILE));

you expect std::ostreambuf_iterator<char> to know how to write std::vector<float> to a stream, but it only knows how to write o char type, look at its assignment operator here: http://en.cppreference.com/w/cpp/iterator/ostreambuf_iterator/operator%3D

I would do it manually:

http://coliru.stacked-crooked.com/a/e7e587c90069a90a

void saveVector(std::string path, const vector<vector<float> >& myVector)
{
    std::ofstream FILE(path, std::ios::out | std::ofstream::binary);

    // Store size of the outer vector
    int s1 = myVector.size();
    FILE.write(reinterpret_cast<const char *>(&s1), sizeof(s1));    

    // Now write each vector one by one
    for (auto& v : myVector) {         
        // Store its size
        int size = v.size();
        FILE.write(reinterpret_cast<const char *>(&size), sizeof(size));

        // Store its contents
        FILE.write(reinterpret_cast<const char *>(&v[0]), v.size()*sizeof(float));
    }
    FILE.close();   
}

void readVector(std::string path,  vector<vector<float> >& myVector)
{
    ifstream FILE(path, std::ios::in | std::ifstream::binary);

    int size = 0;
    FILE.read(reinterpret_cast<char *>(&size), sizeof(size));
    myVector.resize(size);
    for (int n = 0; n < size; ++n) {
        int size2 = 0;
        FILE.read(reinterpret_cast<char *>(&size2), sizeof(size2));
        float f;        
        for ( int k = 0; k < size2; ++k ) {
            FILE.read(reinterpret_cast<char *>(&f), sizeof(f));
            myVector[n].push_back(f);   
        }
    }
}

int main()
{
    std::vector<std::vector<float>> ff;
    ff.resize(10);
    ff[0].push_back(10);
    ff[0].push_back(12);
    saveVector("test.bin", ff);

    std::vector<std::vector<float>> ff2;
    readVector("test.bin", ff2);

    if (ff == ff2) {
        std::cout << "ok!";
    }
}

Upvotes: 4

The Quantum Physicist
The Quantum Physicist

Reputation: 26356

What you're doing up there... is the worst idea in the world! You're writing data that's probably compiler and compiler-version dependent. This is because a vector doesn't contain only the array, but other variables, such as the size of the vector. The order is not specified by the standard, and hence the binary form will be compiler dependent.

You have many options to avoid this:

  1. Flatten your vector and convert it to vector<float>
  2. Use some library to serialize your object, such as Google protocol buffers or boost::serializer
  3. Invent your own (simple) serialization for this particular problem (this is not the best, but it's way better than writing such structures in binary.

If you're using C++03, then you should use the type: vector<vector<float> >, not vector<vector<float>>.

Also pass such objects by reference to avoid copying them. Like this:

void saveVector(const std::string& path, const vector<vector<float>>& myVector)

Upvotes: 4

Related Questions