Writing structures of vectors / std::string into binary file
Hi,
I am using the following structures
struct KeyValPair
{
std::string Key;
std::string Value
};
struct Properties
{
std::string PropertyName;
vector <KeyValPair > PropVal;
};
struct MainComponent
{
std::string MainName;
vector < Properties > Properties;
};
Now in my mail program, I have defined
vector < MainComponent > objComponent;
and I am storing say 10 components values inside this one.
I want these values of the 10 components the next time I execute the program. So the only option I have is to write to file as binary data right ??
Can someone show me how this can be achieved ?
I tried the FILE *fp; thingy and the fwrite and fread
E.g.
FILE*fp;
fp = fopen("c:\\Component.dat","wb");
fwrite(&objComponent,sizeof(objComponent),2,fp);
But i am getting errors. I dont know how to fill parameters for the fwrite since it contains vectors which can be variable.
I am forced to use only standard C++ libraries as this is part of a helper class for a bigger program.
Please do help me.... I am also googling since morning but without much success..
thanks in anticipation.
Also i would be delighted if someone would post with code examples to my program.
Re: Writing structures of vectors / std::string into binary file
You don't have to use FILE and probably shouldn't, as it's not really the "C++ way".You can use ofstream to write data to a file, and ifstream to read from a file.
Code:
std::ofstream stream;
stream.open("test.txt");
if(stream.fail())
throw std::runtime_error("Couldn't open test.txt.");
stream << "blah";
stream.close();
Re: Writing structures of vectors / std::string into binary file
When you have non-POD data (example std::string), there is
no easy way to read/write unformatted (binary). Basically, you
need to do it individually for each data member. I have
a few routines to aid in doing this. I can't post the actual codes,
but I can post some slightly simplified versions (which I have
not tested, but will give you an idea).
A) First, to read/write binary std::strings:
Code:
bool WriteUnformatted_string(std::ostream & out , const std::string & s)
{
std::string::size_type n = s.size();
out.write( reinterpret_cast<const char*>(&n) , sizeof(n) );
if (n > 0)
{
out.write( s.c_str() , n );
}
return !out.bad();
}
bool ReadUnformatted_string(std::istream & in , std::string & s)
{
// Note : With the upcoming changes to the C++ standard,
// you will not need the intermediate vector, since
// a std::string will be gaurenteed to have
// contigous storage (at least, I saw that posted)
std::string::size_type n;
in.read( reinterpret_cast<char*>(&n) , sizeof(n) );
if (n > 0)
{
std::vector<char> v(n);
in.read( &v[0] , n );
s.assign(&v[0],&v[0]+n);
}
else
{
s = "";
}
return !in.bad();
}
B) Next, to read/write unformatted non-POD vectors
Code:
template <typename T>
bool WriteUnformatted_vector_nonPOD(std::ostream & out , const std::vector<T> & v)
{
size_t n = v.size();
out.write( reinterpret_cast<char*>(&n) , sizeof(n) );
for (int i =0; i<n; ++i)
{
v[i].WriteUnformatted(out); // assumes a WriteUnformatted() member function
}
return !out.bad();
}
template <typename T>
bool ReadUnformatted_vector_nonPOD(std::istream & in , std::vector<T> & v)
{
v.clear();
size_t n;
in.read( reinterpret_cast<char*>(&n) , sizeof(n) );
if (n > 0)
{
T key_value;
v.reserve(n);
for (int i =0; i<n; ++i)
{
key_value.ReadUnformatted(in); // assumes a ReadUnformatted() member function
v.push_back(key_value);
}
}
return !in.bad();
}
C) Next modifying your classes
Code:
struct KeyValPair
{
std::string Key;
std::string Value;
bool WriteUnformatted(std::ostream & out) const
{
WriteUnformatted_string(out,Key);
WriteUnformatted_string(out,Value);
return !out.bad();
}
bool ReadUnformatted(std::istream & in)
{
ReadUnformatted_string(in,Key);
ReadUnformatted_string(in,Value);
return !in.bad();
}
};
struct Properties
{
std::string PropertyName;
std::vector <KeyValPair> PropVal;
bool WriteUnformatted(std::ostream & out) const
{
WriteUnformatted_string(out,PropertyName);
WriteUnformatted_vector_nonPOD(out,PropVal);
return !out.bad();
}
bool ReadUnformatted(std::istream & in)
{
ReadUnformatted_string(in,PropertyName);
ReadUnformatted_vector_nonPOD(in,PropVal);
return !in.bad();
}
};
struct MainComponent
{
std::string MainName;
std::vector < Properties > Properties;
bool WriteUnformatted(std::ostream & out) const
{
WriteUnformatted_string(out,MainName);
WriteUnformatted_vector_nonPOD(out,Properties);
return !out.bad();
}
bool ReadUnformatted(std::istream & in)
{
ReadUnformatted_string(in,MainName);
ReadUnformatted_vector_nonPOD(in,Properties);
return !in.bad();
}
};
D) Note: you should open files using ios::binary mode
E) None of this has been tested, but it should give you an
idea of what needs to be done.
Re: Writing structures of vectors / std::string into binary file
I don't think the OP meant that the objects have to be written as binary data, rather that they were unsure if it was the only way to do it.