简体   繁体   中英

How to write an object to file in C++

I have an object with several text strings as members. I want to write this object to the file all at once, instead of writing each string to file. How can I do that?

You can override operator>> and operator<< to read/write to stream.

Example Entry struct with some values:

struct Entry2
{
    string original;
    string currency;

    Entry2() {}
    Entry2(string& in);
    Entry2(string& original, string& currency)
        : original(original), currency(currency)
    {}
};


istream& operator>>(istream& is, Entry2& en);
ostream& operator<<(ostream& os, const Entry2& en);

Implementation:

using namespace std;

istream& operator>>(istream& is, Entry2& en)
{
    is >> en.original;
    is >> en.currency;
    return is;
}

ostream& operator<<(ostream& os, const Entry2& en)
{
    os << en.original << " " << en.currency;
    return os;
}

Then you open filestream, and for each object you call:

ifstream in(filename.c_str());
Entry2 e;
in >> e;
//if you want to use read: 
//in.read(reinterpret_cast<const char*>(&e),sizeof(e));
in.close();

Or output:

Entry2 e;
// set values in e
ofstream out(filename.c_str());
out << e;
out.close();

Or if you want to use stream read and write then you just replace relevant code in operator s implementation.

When the variables are private inside your struct/class then you need to declare operator s as friend methods.

You implement any format/separators that you like. When your string include spaces use getline() that takes a string and stream instead of >> because operator>> uses spaces as delimiters by default. Depends on your separators.

It's called serialization. There are many serialization threads on SO.

There are also a nice serialization library included in boost.

http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/index.html

basically you can do

myFile<<myObject 

and

myFile>>myObject

with boost serialization.

If you have:

struct A {
    char a[30], b[25], c[15];
    int x;
}

then you can write it all just with write(fh, ptr, sizeof(struct a)).

Of course, this isn't portable (because we're not saving the endieness or size of "int," but that may not be an issue for you.

If you have:

struct A {
    char *a, *b, *c;
    int d;
}

then you're not looking to write the object; you're looking to serialize it. Your best bet is to look in the Boost libraries and use their serialization routines, because it's not an easy problem in languages without reflection.

There's not really a simple way, it's C++ after all, not PHP, or JavaScript.

http://www.parashift.com/c++-faq-lite/serialization.html

Boost also has some library for it: http://www.boost.org/doc/libs/release/libs/serialization ... like Tronic already mentioned :)

The better method is to write each field individually along with the string length.

As an alternative, you can create a char array (or std::vector<char> ) and write all the members into the buffer, then write the buffer to the output.

The underlying thorn is that a compiler is allowed to insert padding between members in a class or structure. Use memcpy or std::copy will result in padding bytes written to the output.

Just remember that you need to either write the string lengths and the content or the content followed by some terminating character.

Other people will suggest checking out the Boost Serialization library.

Unfortunately that is generally not quite possible. If your struct only contains plain data (no pointers or complex objects), you can store it as a one chunk, but care must be taken if portability is an issue. Padding, data type size and endianess issues make this problematic.

You can use Boost.Serialization to minimize the amount of code required for proper portable and versionable searialization.

Assuming your goal is as stated, to write out the object with a single call to write() or fwrite() or whatever, you'd first need to copy the string and other object data into a single contiguous block of memory. Then you could write() that block of memory out with a single call. Or you might be able to do a vector-write by calling writev(), if that call is available on your platform.

That said, you probably won't gain much by reducing the number of write calls. Especially if you are using fwrite() or similar already, then the C library is already doing buffering for you, so the cost of multiple small calls is minimal anyway. Don't put yourself through a lot of extra pain and code complexity unless it will actually do some good...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM