从二进制文件中读取动态内存分配的字符串(char*)
read dynamic memory allocated string (char*) from binary file C++
我想让学生数据库通过这种类型:(类学生)
class Student {
unsigned Id;//ID number
char* name;// dynamic memory allocated name (size: 10)
char* family;// dynamic memory allocated last name (size: 10)
int gen;//gender
unsigned MiddleTestGrade;// grade of the student in the middle test
unsigned FinalTestGrade;// grade of the student in the final test
double TotalGrade;// total grade of the student calculates automaticly (dont need to insert this as input)
};
我使用以下命令将所有这些信息写入二进制文件:(StudentData类型是上面提到的Student类)
file.write(reinterpret_cast<const char*>(&StudentData),sizeof(Student));
当我使用read命令从文件中获取所有数据时:
file.read(reinterpret_cast<char*>(&StudentData),sizeof (Student));
的结果是,除了动态分配的名称外,所有内容读起来都很好。这些只包含我写入文件的姓氏。
例如,我在文件中插入2个学生:
12 jhn Sna 1 95 100
和
读取和打印的结果将是:77 David Gen 1 80 85
12 David Gen 1 95 100
和
77 David Gen 1 80 85
当我使用字符串(不是动态分配)时,一切都像它应该的那样工作:
我做错了什么?
当您在struct
中动态分配数据时,您不能使用
file.write(reinterpret_cast<const char*>(&StudentData),sizeof(Student));
写入文件中的所有数据。这只会将结构体中指针的二进制值写入文件。当您恢复它们时,您将只恢复二进制值,这将导致不可预测的行为。
当有动态分配的数据时,需要分别写入struct
的每个字段,并适当地读取它们。
Student
的代码:
// Write Id
file.write(reinterpret_cast<const char*>(&(StudentData.Id)), sizeof(StudentData.Id));
// Get the length of name
// Write the length and then the name
size_t len = strlen(StudentData,name);
file.write(reinterpret_cast<const char*>(&len), sizeof(len));
file.write(StudentData.name, len);
// Get the length of family
// Write the length and then the family
len = strlen(StudentData,family);
file.write(reinterpret_cast<const char*>(&len), sizeof(len));
file.write(StudentData.family, len);
// Write the rest of the data
file.write(reinterpret_cast<const char*>(&(StudentData.gen)), sizeof(StudentData.gen);
file.write(reinterpret_cast<const char*>(&(StudentData.MiddleTestGrade)), sizeof(StudentData.MiddleTestGrade));
file.write(reinterpret_cast<const char*>(&(StudentData.FinalTestGrade)), sizeof(StudentData.FinalTestGrade));
file.write(reinterpret_cast<const char*>(&(StudentData.TotalGrade)), sizeof(StudentData.TotalGrade));
你必须一次读回一个字段的数据,必要时分配内存。
// Read the Id.
file.read(reinterpret_cast<char*>(&StudentData.Id),sizeof (Student.Id));
// Read length of the name
size_t len;
file.read(reinterpret_cast<char*>(&len), sizeof (len));
// Allocate memory for name.
Student.name = new char[len+1];
// Read the name and null-terminate it.
file.read(Student.name, len);
Student.name[len] = ' ';
// Read length of the family
file.read(reinterpret_cast<char*>(&len), sizeof (len));
// Allocate memory for family.
Student.family= new char[len+1];
// Read the family and null-terminate it.
file.read(Student.family, len);
Student.family[len] = ' ';
// Read the rest of the Student data
file.read(reinterpret_cast<char*>(&StudentData.gen),sizeof (Student.gen));
file.read(reinterpret_cast<char*>(&StudentData.MiddleTestGrade),sizeof (Student.MiddleTestGrade));
file.read(reinterpret_cast<char*>(&StudentData.FinalTestGrade),sizeof (Student.FinalTestGrade));
file.read(reinterpret_cast<char*>(&StudentData.TotalGrade),sizeof (Student.TotalGrade));