BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #92282同步于 2016/6/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

[已解决]c++二进制读写

cxh2013
2016/6/25镜像同步18 回复
``` #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进行二进制读写。 ---------分割线------------ 谢谢各位的帮助,我的理解是内存的数据不能直接往文件写,原因是数据的内存分布是未知的。所以需要把结构的数据进行序列化为字节流然后再写入到文件中。详情看七楼的代码。
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
nuanyangyang机器人#1 · 2016/6/25
不是如何“对string”进行二进制读写,而是你要设计你自己的二进制格式。string是C++的类。它仅仅表示一个字符串(一串字符),并没有规定它的二进制表示方法。你要设计“一个string如何表示为二进制的字节序列”。
nuanyangyang机器人#2 · 2016/6/25
另外,你把b1的指着转换成了char*型的:(char *)&b1 你知道转换以后的结果是什么吗?我不认为任何书提到过将struct指针转换成char*指针有什么效果。
Madness机器人#3 · 2016/6/25
不知道二进制怎么做,但是string转char*还是用string自带的c_str好一些。
ivil1995机器人#4 · 2016/6/25
如果你试着用迭代器去查看,并且认真看看,你会发现问题。迭代器访问b2的string时,你会发现它的begin()就是end(),也就是为空,即使你用length()函数获取到的长度并不为空。那么这就有问题了,因为析构的时候是按迭代器析构的,所以当程序结束,string自我析构的时候,你b2里的string就Bong一下,出错了。个人感觉你通过变换指针去修改string的内容,虽然修改了string的buffer,但是会导致string某些数据未更新(比如迭代器),所以这个行为是危险的。
xiaobing307机器人#5 · 2016/6/25
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; }
xiaobing307机器人#6 · 2016/6/25
可以直接转吧 如果把string改成int,应该就不会有问题。 struct B{ int name; int age; }; 【 在 nuanyangyang 的大作中提到: 】 : 另外,你把b1的指着转换成了char*型的:(char *)&b1 : 你知道转换以后的结果是什么吗?我不认为任何书提到过将struct指针转换成char*指针有什么效果。
xiaobing307机器人#7 · 2016/6/25
仅供参考 #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> : ...................
nuanyangyang机器人#8 · 2016/6/25
【 在 xiaobing307 的大作中提到: 】 : 可以直接转吧 : 如果把string改成int,应该就不会有问题。 : struct B{ : ................... 然后就有新的问题了:int的大小是和实现相关的。而且struct里面各个字段的对齐也是和实现相关的。还有整数的字节序也是和实现相关的。
Madness机器人#9 · 2016/6/25
感觉问题是,在read时给string赋值了,但并非通过正常的方式,所以只是修改了buff,却没有正确修改string这个类里的其它数据,于是最后出错了。