//For writing to file:
std::ofstream out(L"abc.txt");
out.write(reinterpret_cast<char*>(&one), sizeof(one)); //one is a vector of structs
ifstream in(L"abc.txt");
in.read(reinterpret_cast<char*>(&one), sizeof(one));
Reading/writing vector to file not working
Basically I have a vector of structs and I'm trying to write them out to a file. I"ve actually done this before with no problems but for some reason I keep getting an error when I try to read from the file I write to, most likely because the data isn't being written.
This is basically the code:
Either the read or write is not working properly or both aren't working properly.
The memory layout of an std::vector instance is unspecified—only the layout of its contents is.
out.write(reinterpret_cast<char*>(&one.first()), one.size() * sizeof(structure));
Quote:Original post by ToohrVykout.write(reinterpret_cast<char*>(&one.front()), one.size() * sizeof(structure));
(It should also be possible to do it with std::copy and an ostreambuf_iterator.)
Quote:Original post by ZahlmanQuote:Original post by ToohrVykout.write(reinterpret_cast<char*>(&one.front()), one.size() * sizeof(structure));
(It should also be possible to do it with std::copy and an ostreambuf_iterator.)
It is, but you will also need a counting iterator (such as libindustry's n_iterator adaptor) if you don't want to read in the whole file (unless you know of another way -- I wouldn't be surprised):
std::ofstream out( "abc.txt", std::ios::binary );std::copy( one.begin(), one.end(), std::ostreambuf_iterator< char >( out ) )std::ofstream in( "abc.txt", std::ios::binary );std::copy( industry::make_n_iterator( std::istreambuf_iterator< char >( in ) ), industry::make_n_iterator( std::istreambuf_iterator< char >(), one.size() ), one.begin() )
OP: you probably want to use std::ios::binary as well so that \r and \r\n aren't transformed to \n.
jfl.
Quote:Original post by jflanglois
It is, but you will also need a counting iterator (such as libindustry's n_iterator adaptor) if you don't want to read in the whole file (unless you know of another way -- I wouldn't be surprised):
If you're relying on external libraries, you may as well use SGI's copy_n instead of std::copy.
And writing structs inside the vector also shouldn't be done with direct memory access. Member alignment and all that.
See this for a general overview of problems:
http://www.parashift.com/c++-faq-lite/serialization.html
Something like this:
You then need to provide load/save pairs for every type you wish to support, and every container you use. If you use templates, you can provide generic support for all container types without knowing in advance how they'll be specialized.
Templates also allow a lot of simplification here, but that isn't necessary if you have only a few types.
There's also a small problem with operator precedence (s << x << y), which isn't strictly define. So a completely safe solution would be (s << x; s << y; ), but I never encountered problems using the first syntax.
Also, strings are containers of basic_string type. You need to handle them in the same way as other STL containers, by writing each character out individually. Although they are stored in memory sequentially, this storage isn't specified (especially with unicode), where changing compilation settings could make your serialized files incompatible.
See this for a general overview of problems:
http://www.parashift.com/c++-faq-lite/serialization.html
Something like this:
struct my_type { int x; double y;};void save( std::ostream &s, const my_type &value ) { s << value.x << value.y;}void load( std::istream &s, my_type &value ) { s >> value.x >> value.y;}template < class T >void save( std::ostream &s, const std::vector< T > &e ){ s << e.size(); std::vector<T>::const_iterator i = e.begin(); while ( i != e.end() ) { save( s, (*e) ); }}template < class T >void load( std::ostream &s, std::vector< T > &e ){ int count = 0; s >> count; e.clear(); for ( int i = 0; i < count; i++ ) { T tmp; load( s, tmp ); e.push_back( tmp ); }}
You then need to provide load/save pairs for every type you wish to support, and every container you use. If you use templates, you can provide generic support for all container types without knowing in advance how they'll be specialized.
Templates also allow a lot of simplification here, but that isn't necessary if you have only a few types.
There's also a small problem with operator precedence (s << x << y), which isn't strictly define. So a completely safe solution would be (s << x; s << y; ), but I never encountered problems using the first syntax.
Also, strings are containers of basic_string type. You need to handle them in the same way as other STL containers, by writing each character out individually. Although they are stored in memory sequentially, this storage isn't specified (especially with unicode), where changing compilation settings could make your serialized files incompatible.
Quote:Original post by ToohrVyk
If you're relying on external libraries, you may as well use SGI's copy_n instead of std::copy.
Well, the problem with copy_n is that it only stops on the count condition, so you won't be able to deal with EOF or similar issues.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement