Serialize and deserialize a vector in binary

I am having problems serializing a vector (std :: vector) in binary format, and then correctly deserialize it and can read the data. This is my first time using the binary format (I used ASCII, but now it has become too difficult to use), so I just start with a simple vector ints.

Whenever I read data back, the vector always has the desired length, but the data is 0, undefined or random.

class Example { public: std::vector<int> val; }; 

Write

 Example example = Example(); example.val.push_back(10); size_t size = sizeof BinaryExample + (sizeof(int) * example.val.size()); std::fstream file ("Levels/example.sld", std::ios::out | std::ios::binary); if (file.is_open()) { file.seekg(0); file.write((char*)&example, size); file.close(); } 

READ:

 BinaryExample example = BinaryExample(); std::ifstream::pos_type size; std::ifstream file ("Levels/example.sld", std::ios::in | std::ios::binary | std::ios::ate); if (file.is_open()) { size = file.tellg(); file.seekg(0, std::ios::beg); file.read((char*)&example, size); file.close(); } 

Does anyone know what I'm doing wrong or what to do or be able to point me in the direction that I need to do?

+4
source share
4 answers

You cannot serialize a non-POD class by replacing an existing instance, as you seem to be trying to do - you need to provide the class with a constructor that reads the data from the stream and creates a new instance of the class with it.

In outline, given something like this:

 class A { A(); A( istream & is ); void serialise( ostream & os ); vector <int> v; }; 

then serialise () will write the length of the vector, followed by the vector content. The constructor will read the length of the vector, resize the vector in length, then read the contents of the vector:

 void A :: serialise( ostream & os ) { size_t vsize = v.size(); os.write((char*)&vsize, sizeof(vsize)); os.write((char*)&v[0], vsize * sizeof(int) ); } A :: A( istream & is ) { size_t vsize; is.read((char*)&vsize, sizeof(vsize)); v.resize( vsize ); is.read((char*)&v[0], vsize * sizeof(int)); } 
+5
source

You are using the address of the vector. What you need / need is the address of the data held by the vector. Writing, for example, would be something like:

 size = example.size(); file.write((char *)&size, sizeof(size)); file.write((char *)&example[0], sizeof(example[0] * size)); 
+2
source

I would write in network byte order so that the file can be written and read on any platform. So:

 #include <fstream> #include <iostream> #include <iomanip> #include <vector> #include <arpa/inet.h> int main(void) { std::vector<int32_t> v = std::vector<int32_t>(); v.push_back(111); v.push_back(222); v.push_back(333); { std::ofstream ofs; ofs.open("vecdmp.bin", std::ios::out | std::ios::binary); uint32_t sz = htonl(v.size()); ofs.write((const char*)&sz, sizeof(uint32_t)); for (uint32_t i = 0, end_i = v.size(); i < end_i; ++i) { int32_t val = htonl(v[i]); ofs.write((const char*)&val, sizeof(int32_t)); } ofs.close(); } { std::ifstream ifs; ifs.open("vecdmp.bin", std::ios::in | std::ios::binary); uint32_t sz = 0; ifs.read((char*)&sz, sizeof(uint32_t)); sz = ntohl(sz); for (uint32_t i = 0; i < sz; ++i) { int32_t val = 0; ifs.read((char*)&val, sizeof(int32_t)); val = ntohl(val); std::cout << i << '=' << val << '\n'; } } return 0; } 
+2
source

Read another answer to find out how you should read / write binary structure.

I add this because I think your motives for using the binary format are wrong. The binary format will not be easier than ASCII, usually the opposite.

You have many options for saving / reading data for long-term use (ORM, databases, structured formats, configuration files, etc.). A flat binary is usually worse and harder to maintain, with the exception of very simple structures.

+1
source

All Articles