繁体   English   中英

C ++:从二进制文件读取输入时出现问题

[英]C++: Problems reading input from a binary file

我在AccountManagement.cpp中有一个AccountManagement类。 我在Account.cpp中有另一个称为Account的类。 我有一个模板,可以使用OrdereList类对列表中的给定数据进行排序,该类还具有自己的迭代器。 AccountManagement类以二进制文件输出“帐户”列表,如下所示:

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

我不知道MYLIB::Date类,但是在那里有一个std::string对象就足够了。

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

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

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


免责声明: 它将在小型嵌入式系统的工作有一个统一的地址映射,遗憾的是所有的投标面向用户的操作系统(如Windows,OSX和Linux)有进程之间独立的地址空间和墙壁。

如果您保存对象并将其再次加载到同一对象中, 并且同时未更改字符串,则您的函数AccountManagement::output()会给人以完美的印象。

怎么了 ?

一旦您的对象不再是POD对象(即,它包含使用指针或虚拟函数等的数据),您就不能仅通过将其内存写入磁盘来保存它。

在您的情况下,第二个功能由于这个原因而失败。 第一个功能仅给人以实用的印象。 该字符串是一个复杂的对象,该对象在某处存储指向动态分配的内存的指针。 如果您编写对象并照原样读取它,而不更改对象,则只需重新读取内存中的值即可。 读取的隐藏指针的值恰好是读取前的值。 那是非常幸运的情况。 但是在大多数情况下,它将失败。

怎么解决呢?

要保存对象,您应该对其进行序列化:使用适当的功能将每个组件分别写入/读取到文件中。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM