Reputation: 319
I am working on a problem, and I am not sure if I'm doing this properly, or if I even have the right approach at all. My code, so far, just gives me segfaults.
I have a simple little receipt writing program to practice some C++ concepts, one of them being file i/o in binary. I have a couple arrays holding data (one holding strings of a service type, the other holding corresponding double costs). I have a little menu, and the writing in binary part goes fine. However, I am not sure how to read these back from the file.
I am currently using a structure to hold various data members (customer's name, total charges, etc.), and I want to write all of the services they chose, along with their corresponding prices, to a file, and then be able to read them back. These are currently stored in vectors in the structure.
I think I understand how to read/write strings to/from a binary file (write the length of the string, then the data, then read the length back, then read that many bytes into a string). But how do I do this with a vector? I understand how it can be done with, say, a vector of fixed-size members (i.e. ints), but what about a vector of strings? In this case, the members do not have a set size, so I am not sure how to read them back.
Is this even possible? If anyone could point me in the right direction, that would be extremely helpful. There was a similar forum posting a year or so ago, but it didn't help me much.
tl;dr -- How do I read a variable-size vector of variable-length strings from a binary file?
Upvotes: 0
Views: 1424
Reputation: 1780
You need to package or encapsulate your data into objects and to serialize them out, as Mark pointed it out using http://www.boost.org/doc/libs/1_49_0/libs/serialization/doc/index.html. You can find examples and detailed help there. Search for a very simple case. :)
Edit: I have done for you a quick and dirty example. Enjoy. (Apologies for the formatting.)
#include <cstddef> // NULL
#include <iomanip>
#include <iostream>
#include <fstream>
#include <iterator>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
class family_names
{
friend class boost::serialization::access;
std::vector<std::string> m_names;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & m_names;
}
friend std::ostream & operator<<(std::ostream &os, const family_names& fn);
public:
family_names(const std::vector<std::string>& names)
: m_names(names)
{}
family_names() {}
};
std::ostream & operator<<(std::ostream &os, const family_names& fn)
{
std::ostream_iterator<std::string> out_it (std::cout,", ");
std::copy(fn.m_names.begin(), fn.m_names.end(), out_it);
return os;
}
void save(const family_names &s, const char * filename){
// make an archive
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
oa << s;
}
void restore(family_names &s, const char * filename)
{
// open the archive
std::ifstream ifs(filename);
boost::archive::text_iarchive ia(ifs);
// restore the family names from the archive
ia >> s;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<std::string> vec_names;
vec_names.push_back("Jason");
vec_names.push_back("Mark");
vec_names.push_back("Ludmilla");
family_names names(vec_names);
std::string filename = "c:\\Dev\\demofile.txt";
std::cout << names << std::endl;
save(names, filename.c_str());
family_names names_back;
restore(names_back, filename.c_str());
std::cout << names_back << std::endl;
return 0;
}
Upvotes: 1
Reputation: 591
I guess you use >> and << operators, I recommend you to try it with ofstream::write and ifstream::read for binary manipulation.
Upvotes: 0
Reputation: 168826
To paraphrase:
> How do I read the length back, then read that many bytes into a string with a vector?
One string at a time:
// Untested
std::vector<std::string> ReadSomeStrings(std::istream& inFile, size_t howMany) {
std::vector<std::string> result;
for(int i = 0; i < howMany; ++i) {
std::size_t len;
is.read(&len, sizeof len);
std::string s(len, '\0');
is.read(&s[0], s.size());
result.push_back(s);
}
return result;
}
Upvotes: 1