C++ C++;:从二进制文件读取输入时出现问题
我在AccountManagement.cpp有一个AccountManagement班。我在Account.cpp中有另一个名为Account的类。我有一个模板,它使用OrderList类对列表中的给定数据进行排序,OrderList类也有自己的迭代器。AccountManagement类以二进制文件的形式输出帐户列表,如下所示:C++ C++;:从二进制文件读取输入时出现问题,c++,class,binaryfiles,C++,Class,Binaryfiles,我在AccountManagement.cpp有一个AccountManagement班。我在Account.cpp中有另一个名为Account的类。我有一个模板,它使用OrderList类对列表中的给定数据进行排序,OrderList类也有自己的迭代器。AccountManagement类以二进制文件的形式输出帐户列表,如下所示: void AccountManagement::saveData(const char * file) //saves data in the specified
void AccountManagement::saveData(const char * file) //saves data in the specified binary file
{
ofstream out(file, ios::out | ios::binary);
if(!out)
{
cerr<<"Problem opening output file!"<<endl;
}
OrderedList<Account>::iterator it = this->account_manager.begin();
for(int i = 0; i < this->total_accounts; i++)
{
Account temp = *it;
out.write((char*)&temp, sizeof(Account));
it++;
}
out.close();
}
void AccountManagement::saveData(const char*file)//将数据保存在指定的二进制文件中
{
流输出(文件,ios::out | ios::binary);
如果(!out)
{
cerr我不知道MYLIB::Date
类,但是在那里有一个std::string
对象就足够了
std::string
对象动态分配内存以适应其包含的字符串。而堆上分配的内存仅对当前进程可用,您不能保存指针(位于std::string
类中)并从其他进程加载它,希望该指针处有有效内存
如果您在一个进程中保存指向动态分配内存的指针,并从另一个进程加载和使用它,那么您将具有未定义的行为
您需要保存该字符串。也可能是MYLIB::Data
对象
免责声明:它将在具有单一统一地址映射的小型嵌入式系统上工作,不幸的是,所有面向用户的操作系统(如Windows、OSX和Linux)在进程之间有单独的地址空间和墙。我不知道MYLIB::Date
类,但是在其中有std::string
对象就足够了
std::string
对象动态分配内存以适应其包含的字符串。而堆上分配的内存仅对当前进程可用,您不能保存指针(位于std::string
类中)并从其他进程加载它,希望该指针处有有效内存
如果您在一个进程中保存指向动态分配内存的指针,并从另一个进程加载和使用它,那么您将具有未定义的行为
您需要保存该字符串。也可能是MYLIB::Data
对象
免责声明:它将在具有单一统一地址映射的小型嵌入式系统上工作,不幸的是,所有面向用户的操作系统(如Windows、OSX和Linux)在进程之间有单独的地址空间和墙。我不知道MYLIB::Date
类,但是在其中有std::string
对象就足够了
std::string
对象动态分配内存以适应其包含的字符串。而堆上分配的内存仅对当前进程可用,您不能保存指针(位于std::string
类中)并从其他进程加载它,希望该指针处有有效内存
如果您在一个进程中保存指向动态分配内存的指针,并从另一个进程加载和使用它,那么您将具有未定义的行为
您需要保存该字符串。也可能是MYLIB::Data
对象
免责声明:它将在具有单一统一地址映射的小型嵌入式系统上工作,不幸的是,所有面向用户的操作系统(如Windows、OSX和Linux)在进程之间有单独的地址空间和墙。我不知道MYLIB::Date
类,但是在其中有std::string
对象就足够了
std::string
对象动态分配内存以适应其包含的字符串。而堆上分配的内存仅对当前进程可用,您不能保存指针(位于std::string
类中)并从其他进程加载它,希望该指针处有有效内存
如果您在一个进程中保存指向动态分配内存的指针,并从另一个进程加载和使用它,那么您将具有未定义的行为
您需要保存该字符串。也可能是MYLIB::Data
对象
免责声明:它适用于具有单一统一地址映射的小型嵌入式系统,不幸的是,所有面向用户的操作系统(如Windows、OSX和Linux)在进程之间都有单独的地址空间和墙。您的函数AccountManagement::output()
给人的印象是,如果保存对象并将其再次加载到同一个对象中,和同时字符串没有更改,则它可以完美地工作
怎么了?
一旦您的对象不再是POD对象(即,它包含使用指针或使用虚拟函数等的数据),您就不能仅仅通过将其内存写入磁盘来保存它
在您的例子中,第二个函数由于这个原因失败。第一个函数只是给人一种工作的印象。字符串是一个复杂的对象,它在某处存储指向动态分配内存的指针。如果您像以前那样写入对象并将其读回,而不更改对象,那么内存中的值将被简单地重新读取。读取的隐藏指针的值与读取之前的值完全相同。这是一个非常幸运的情况。但在大多数情况下,它会失败
如何解决它?
要保存对象,应将其序列化:使用适当的函数将每个组件分别写入/读取到文件中
要做到这一点,最简单的方法是使用一些现有的序列化库,例如您的函数AccountManagement::output()
void AccountManagement::output()
{
ifstream in("accounts.dat", ios::in | ios::binary);
if(!in)
{
cerr<<"File doesn't exist!"<<endl;
exit(1);
}
Account acc;
while(in.read((char*)&acc, sizeof(Account)))
{
cout<<acc;
}
in.close();
}
void loadData()
{
ifstream in("accounts.dat", ios::in | ios::binary);
if(!in)
{
cerr<<"File doesn't exist!"<<endl;
exit(1);
}
Account acc;
while(in.read((char*)&acc, sizeof(Account)))
{
cout<<acc;
}
in.close();
}
class Account
{
friend ostream& operator<<(ostream&,const Account&); //overloading << operator
friend istream& operator>>(istream&,Account&); //overloading >> operator
public:
void operator=(const Account&); //overloading = operator
bool operator<=(const Account&); //overloading <= operator
bool operator<(const Account&); //overloading < operator
private:
string number; //Account Number
char name[100]; //Account holder's name
char sex; //M or F indicating the gender of account holder
MYLIB::Date dob; //date of birth of account holder
char address[100]; //address of account holder
char balance[20]; //balance of account holder
};