C ++:从二进制文件读取输入的问题

时间:2015-05-30 14:24:04

标签: c++ class binaryfiles

我在AccountManagement.cpp中有一个AccountManagement类。我在Account.cpp中有另一个名为Account的类。我有一个模板,使用OrdereList类对列表中的给定数据进行排序,OrdereList类也有自己的迭代器。 AccountManagement类在二进制文件中输出Accounts列表,如下所示:

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();
}

我在AccountManagement类中定义了一个以下函数,它从二进制文件中读取所有数据并输出它。这个功能非常好。它显示在这里:

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();
}

但是,当我在另一个文件中使用同一个函数(具有不同的名称)时,它也有Account.h头文件以从同一个“account.dat”文件中检索数据,这给了我分段错误。可能是什么问题呢?以下是功能:

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
};

2 个答案:

答案 0 :(得分:3)

我不了解MYLIB::Date课程,但在那里你有一个std::string对象就足够了。

std::string对象动态分配内存 以适合它包含的字符串。并且在堆上分配的内存仅对当前进程可用,您不能保存指针(位于std::string类内)并从其他进程加载它并希望在有效内存时指针。

如果在一个进程中保存指向动态分配的内存的指针,并从另一个进程加载并使用它,那么您将有未定义的行为

您需要serialize字符串才能保存它。也可能是MYLIB::Data对象。

免责声明:在具有单一统一地址映射的小型嵌入式系统上工作,不幸的是,所有面向用户的投标操作系统(如Windows,OSX和Linux)都有单独的地址空间和墙进程之间。

答案 1 :(得分:0)

如果您保存对象并将其再次加载到同一对象中,那么您的函数AccountManagement::output()会给出完美的效果,前提是字符串在此期间未发生变化。

出了什么问题?

只要您的对象不再是POD对象(即它包含使用指针的数据,或使用虚函数等等),您只需将其内存写入其中即可保存它。磁盘。

在您的情况下,第二个函数因此失败。第一个功能只给人一种印象。该字符串是一个复杂的对象,它存储指向动态分配的内存的某些指针。如果您编写对象并按原样读取它,而不更改对象,则只需重新读取内存中的值。读取的隐藏指针的值与读取之前的值完全相同。这是一个非常幸运的情况。但在大多数情况下,它会失败。

如何解决?

要保存对象,您应该对其进行序列化:使用适当的函数将每个组件分别写入/重新分配到文件。

最简单的方法是使用一些现有的序列化库,例如 boost serialization