C++序列化只检索字符串的一半



我有一个类要序列化:(私有属性)

class Task {
public:
enum Status { COMPLETED, PENDIENT };
// GETTERS SETTERS... 
// UTILS
const std::ostream& storeTask( std::ostream &stream );
const std::istream& retrieveTask( std::istream &stream );
private:
void setID();
static int sCount;
int id;
std::string text;
Status status;
tm timestamp;
};

正如你所看到的,我正试图通过实现storeTaskretrieveTask方法来做到这一点,我这样定义:

// SERIALIZATION
const std::ostream& Task::storeTask( std::ostream &stream ) {
stream.write((char *) &id, sizeof(int));
stream.write((char *) text.c_str(), sizeof(text.length()));
stream.write((char *) &status, sizeof(Status));
stream.write((char *) &timestamp, sizeof(tm));
return stream;
}
const std::istream& Task::retrieveTask( std::istream &stream ) {
stream.read((char *) &id, sizeof(int));
stream.read((char *) text.c_str(), sizeof(text.length()));
stream.read((char *) &status, sizeof(Status));
stream.read((char *) &timestamp, sizeof(tm));
return stream;
}

我通过创建一个由2个Task对象组成的向量来测试实现,使用它们的storeTask方法编写它们,然后创建另一个包含2个不同Task的Task向量,并尝试将Task向量编号1的值重新加载到第二个向量。

用这两个任务编写二进制文件似乎很好,但当再次读取它们时,它只获取文本字符串的4个第一个字符。

int main() {
std::vector<Task> myTasks;
Task task1("First Task");
Task task2("Second Task");
myTasks.push_back(task1);
myTasks.push_back(task2);
std::vector<Task> myTasks2;
Task task3("Task num1");
Task task4("Task num2");
myTasks2.push_back(task3);
myTasks2.push_back(task4);
writeTasks(myTasks);
readTasks(myTasks2);
return 0;
}
void writeTasks(std::vector<Task> aTasks) {
std::fstream fileStream("fileStream", std::ios::out | std::ios::binary);
for ( int x = 0; x < aTasks.size(); x++ ) {
std::cout << "Storing: " << aTasks[x].getText() << "n";
aTasks[x].storeTask(fileStream);
}
fileStream.close();
}
void readTasks(std::vector<Task> aTasks) {
std::fstream fileStream;
fileStream.open("fileStream", std::ios::in | std::ios::binary);
for ( int x = 0; x < aTasks.size(); x++ ) {
std::cout << "Retrieving " << aTasks[x].getText();
aTasks[x].retrieveTask(fileStream);
std::cout << " as --> " << aTasks[x].getText() << " - " << aTasks[x].getTime() << "n";
}
fileStream.close();
}

然后返回:

Storing: First Task
Storing: Second Task
Retrieving Task num1 as --> Firs num1 - 01:02:26
Retrieving Task num2 as --> Seco num2 - 01:02:26

何时返回:

Storing: First Task
Storing: Second Task
Retrieving Task num1 as --> First Task - 01:02:26
Retrieving Task num2 as --> Second Task - 01:02:26

有什么想法吗?不知道问题是写二进制序列化还是读二进制序列化。。。其他值,如时间、日期似乎也很有效。

text.c_str()返回一个const char *时,我声明了一个从字符串转换为char*的小函数:

char * str_to_char(std::string s) {
char *a=new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
return a;
}

并在retireveTask方法中尝试了这一点:

stream.read(str_to_char(text), text.size() + 1);

但是得到了:

Storing: First Task
Storing: Second Task
Retrieving Task num1 as --> Task num1 - 589824:524288:131072
Retrieving Task num2 as --> Task num2 - 112:09:08

您有两个主要问题:

  1. 在写sizeof(text.length()))时。该sizeof运算符返回text.length()返回的std::string::size_type的大小(通常为4或8字节)。仅使用text.length()

  2. 阅读时,请尝试直接将文本放入字符串中。这肯定不会起作用,因为实际字符串可能甚至没有分配,或者没有分配足够的空间。我想说,你很幸运,你能读到一些东西,而且你的程序没有在这里崩溃。

要序列化字符串(或任何可变大小的数据),您需要首先存储字符串的长度,这样您就知道以后要读取多少。

正确的序列化并不容易,我真的建议您研究Boost序列化,它可以正确处理所有的奇怪情况和角落情况。

最新更新