我有一个带有多个文本字符串作为成员的对象。我想一次性将这个对象写入文件,而不是将每个字符串写入文件。我怎么能这样做?
答案 0 :(得分:10)
您可以覆盖operator>>
和operator<<
来读/写流。
示例Entry struct
包含一些值:
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);
实现:
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;
}
然后打开文件流,并为您调用的每个对象打开:
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();
或输出:
Entry2 e;
// set values in e
ofstream out(filename.c_str());
out << e;
out.close();
或者,如果您想使用流read
和write
,那么您只需替换operator
实施中的相关代码。
当变量在struct / class中是私有的时,你需要将operator
声明为友元方法。
您可以实现任何您喜欢的格式/分隔符。当你的字符串包含空格时,使用getline()接受字符串和流而不是>>
,因为operator>>
默认使用空格作为分隔符。取决于你的分隔符。
答案 1 :(得分:6)
这叫做序列化。 SO上有许多序列化线程。
boost中还包含一个很好的序列化库。
http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/index.html
基本上你可以做到
myFile<<myObject
和
myFile>>myObject
使用boost序列化。
答案 2 :(得分:4)
如果你有:
struct A {
char a[30], b[25], c[15];
int x;
}
然后你可以用write(fh,ptr,sizeof(struct a))来编写它。
当然,这不是可移植的(因为我们没有保存“int”的结尾或大小,但这对你来说可能不是问题。
如果你有:
struct A {
char *a, *b, *c;
int d;
}
然后你不打算写这个对象;你想要序列化它。最好的办法是查看Boost库并使用它们的序列化例程,因为在没有反射的语言中这不是一个简单的问题。
答案 3 :(得分:1)
没有一种简单的方法,毕竟它是C ++,而不是PHP或JavaScript。
http://www.parashift.com/c++-faq-lite/serialization.html
Boost也有一些库:http://www.boost.org/doc/libs/release/libs/serialization ...就像Tronic已经提到的那样:)
答案 4 :(得分:1)
更好的方法是单独编写每个字段以及字符串长度。
作为替代方法,您可以创建一个char
数组(或std::vector<char>
)并将所有成员写入缓冲区,然后将缓冲区写入输出。
潜在的棘手是允许编译器在类或结构中的成员之间插入填充。使用memcpy
或std::copy
将导致填充字节写入输出。
请记住,您需要编写字符串长度和内容或内容,后跟一些终止字符。
其他人会建议查看Boost序列化库。
答案 5 :(得分:0)
不幸的是,这通常不太可能。如果您的结构只包含纯数据(没有指针或复杂对象),您可以将它存储为一个块,但如果可移植性是一个问题,必须小心。填充,数据类型大小和字节序问题使这成为问题。
您可以使用Boost.Serialization来最小化正确的可移植和可版本化的searialization所需的代码量。
答案 6 :(得分:0)
假设您的目标如上所述,只需调用write()或fwrite()或其他任何东西来写出对象,您首先需要将字符串和其他对象数据复制到一个连续的内存块中。然后你可以通过一次调用写出()该内存块。或者,如果您的平台上有该调用,则可以通过调用writev()来执行向量写入。
也就是说,通过减少写入呼叫的数量,你可能不会获得太多收益。特别是如果你已经使用fwrite()或类似的,那么C库已经为你做了缓冲,所以无论如何多个小调用的成本是最小的。不要让自己经历许多额外的痛苦和代码复杂性,除非它实际上会做一些好事......