Jump to content
  • Advertisement
Sign in to follow this  
chillypacman

Reading/writing vector to file not working

This topic is 4191 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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:
//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));
Either the read or write is not working properly or both aren't working properly.

Share this post


Link to post
Share on other sites
Advertisement
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));

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
out.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.)

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Quote:
Original post by ToohrVyk
out.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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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:

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!