返回信息流```
#include <fstream>
#include <iostream>
using namespace std;
struct B{
string name;
int age;
};
int main(){
ofstream operson("person", ios::binary);
B b1;
b1.name = "beijing";
b1.age = 60;
operson.write((char *)&b1, sizeof(B));
operson.close();
ifstream iperson("person", ios::binary);
B b2;
iperson.read((char *)&b2, sizeof(B));
cout << b2.name << endl << b2.age << endl;
iperson.close();
}
```
代码出现段错误,是因为string吗,应该怎样对string进行二进制读写。
---------分割线------------
谢谢各位的帮助,我的理解是内存的数据不能直接往文件写,原因是数据的内存分布是未知的。所以需要把结构的数据进行序列化为字节流然后再写入到文件中。详情看七楼的代码。
这是一条镜像帖。来源:北邮人论坛 / cpp / #92282同步于 2016/6/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
[已解决]c++二进制读写
cxh2013
2016/6/25镜像同步18 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
不是如何“对string”进行二进制读写,而是你要设计你自己的二进制格式。string是C++的类。它仅仅表示一个字符串(一串字符),并没有规定它的二进制表示方法。你要设计“一个string如何表示为二进制的字节序列”。
另外,你把b1的指着转换成了char*型的:(char *)&b1
你知道转换以后的结果是什么吗?我不认为任何书提到过将struct指针转换成char*指针有什么效果。
如果你试着用迭代器去查看,并且认真看看,你会发现问题。迭代器访问b2的string时,你会发现它的begin()就是end(),也就是为空,即使你用length()函数获取到的长度并不为空。那么这就有问题了,因为析构的时候是按迭代器析构的,所以当程序结束,string自我析构的时候,你b2里的string就Bong一下,出错了。个人感觉你通过变换指针去修改string的内容,虽然修改了string的buffer,但是会导致string某些数据未更新(比如迭代器),所以这个行为是危险的。
b1.name = "beijing"; // "beijing"并不是直接存储在string类里面
lz可以跑一下下面的代码,看看输出是什么
#include <iostream>
#include <string>
using namespace std;
int main() {
string a = "a";
cout << a << ":\t" << sizeof(a) << endl;
a = "0123456789";
cout << a << ":\t" << sizeof(a) << endl;
return 0;
}
可以直接转吧
如果把string改成int,应该就不会有问题。
struct B{
int name;
int age;
};
【 在 nuanyangyang 的大作中提到: 】
: 另外,你把b1的指着转换成了char*型的:(char *)&b1
: 你知道转换以后的结果是什么吗?我不认为任何书提到过将struct指针转换成char*指针有什么效果。
仅供参考
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
struct B{
string name;
int age;
int serial(char* buf, int size);
bool deserial(char* buf, int size);
};
int B::serial(char* buf, int size) {
int need_size = name.size() + sizeof(int) + sizeof(int);
if (size < need_size) {
cerr << "need bigger buf, given_size=" << size << " need_size=" << need_size << endl;
return -1;
}
char* buf_ori = buf;
int name_len = name.size();
memcpy(buf, &name_len, sizeof(int));
buf += sizeof(int);
if (!name.empty()) {
memcpy(buf, &name[0], name.size());
buf += name.size();
}
memcpy(buf, &age, sizeof(int));
buf += sizeof(int);
return buf - buf_ori;
}
bool B::deserial(char* buf, int size) {
if (size < sizeof(int) + sizeof(int)) {
cerr << "invalid parameter, size=" << size << endl;
return false;
}
int name_size = *(int*)buf;
buf += sizeof(int);
int expect_size = name_size + sizeof(int) + sizeof(int);
if (size < expect_size) {
cerr << "error, expect_size=" << expect_size << ", size=" << size << endl;
return false;
}
name.resize(name_size);
memcpy(&name[0], buf, name_size);
buf += name_size;
age = *(int*)buf;
return true;
}
int main(){
ofstream operson("person", ios::binary);
B b1;
b1.name = "beijing";
b1.age = 60;
char buf[1024];
int size = b1.serial(buf, sizeof(buf));
if (size == -1) {
operson.close();
return -1;
}
operson.write(buf, size);
operson.close();
ifstream iperson("person", ios::binary);
B b2;
iperson.read(buf, sizeof(buf));
if (b2.deserial(buf, sizeof(buf))) {
cout << b2.name << endl << b2.age << endl;
}
iperson.close();
}
【 在 cxh2013 的大作中提到: 】
: [md]
: ```
: #include <fstream>
: ...................
【 在 xiaobing307 的大作中提到: 】
: 可以直接转吧
: 如果把string改成int,应该就不会有问题。
: struct B{
: ...................
然后就有新的问题了:int的大小是和实现相关的。而且struct里面各个字段的对齐也是和实现相关的。还有整数的字节序也是和实现相关的。
感觉问题是,在read时给string赋值了,但并非通过正常的方式,所以只是修改了buff,却没有正确修改string这个类里的其它数据,于是最后出错了。