加载和保存向量到一个文件(Loading and Saving vectors to a file)

2019-07-31 13:48发布

我使用C ++ Builder和我的向量阵列Appointment的对象。

我想将它保存到并从文件加载它。

目前,我使用ifstream的和ofstream的二进制文件。 我有一个包含将被保存旁边的数据向量的大小,从而装载时就知道它的大小标题。

是serilization更好的方式来做到这一点?

如果是这样,我需要使用Boost库,还是另辟蹊径?

这里是我当前的代码:

class appointment
{
public:
    appointment();
    appointment(TDateTime aDate, TDateTime aReminderDateTime, string aType,
    string aLocation, string aComments, bool aIsImportant)
    {
        appDateTime = aDate;
        appReminderDateTime = aReminderDateTime;
        appType = aType;
        appLocation = aLocation;
        appComments = aComments;
        appIsImportant = aIsImportant;
    }
    void setAppDateTime(TDateTime aDateTime)
    {
        appDateTime = aDateTime;
    }
    void setappReminderDateTime(TDateTime aReminderDateTime)
    {
        appReminderDateTime = aReminderDateTime;
    }
    /*
    void printAppointmentDetails()
    {
        cout << "Appointment Date: " << appDateTime << endl;
        cout << "Appointment Reminder Date: " << appReminderDateTime << endl;
        cout << "Appointment Type: " << appType << endl;
        cout << "Appointment Location: " << appLocation << endl;
        cout << "Appointment Comments: " << appComments << endl;
        if (appIsImportant)
        {
            cout << "Appointment IsImportant: " << "Yes" << endl;
        } else {
            cout << "Appointment IsImportant: " << "No" << endl;
        }
    }

    */
    void setType(string aType)
    {
        appType = aType;
    }
    void setLocation(string aLocation)
    {
        appLocation = aLocation;
    }
    void setComments(string aComments)
    {
        appComments = aComments;
    }
    void setIsImportant(bool aIsImportant)
    {
        appIsImportant = aIsImportant;
    }
    TDateTime getAppDateTime()
    {
        return appDateTime;
    }
    TDateTime getAppReminderDateTime()
    {
        return appReminderDateTime;
    }
    string getType()
    {
        return appType;
    }
    string getLocation()
    {
        return appLocation;
    }
    string getComments()
    {
        return appComments;
    }
    bool getIsImportant()
    {
        return appIsImportant;
    }
private:
    //appointment();
    TDateTime appDateTime;
    TDateTime appReminderDateTime;
    string appType;
    string appLocation;
    string appComments;
    bool appIsImportant;
    //person owner;
};

class calendar
{
public:
    calendar()
    {
        //loadFromFile();
        //load persons
        //calculateimportantAppointments
    }
    ~calendar()
    {
        saveToFile();
    }
    //addperson
    //editperson
    //removeperson
    void createAppointment(TDateTime aDate, TDateTime aReminderDateTime, string aType,
    string aLocation, string aComments, bool aIsImportant)
    {
        appointment newAppointment(aDate, aReminderDateTime, aType,
        aLocation, aComments, aIsImportant);
        appointments.push_back(newAppointment);
    }
    /*
    void printAllAppointmentDetails()
    {
        for (int i = 0; i < appointments.size(); i++)
        {
            appointments[i].printAppointmentDetails();
        }
    }
    void calculateImportantAppointments()
    {

    }
    int getNumberOfImportantAppointments()
    {
        int intImportantAppointmentCount = 0;
        for (int i = 0; i < appointments.size(); i++)
        {
             if (appointments[i].getIsImportant())
                intImportantAppointmentCount += 1;
        }
        return intImportantAppointmentCount;
    }

    appointment[] getImportantAppointments()
    {

    }
    appointment[] getAllAppointments()
    {

    }
    */
    void loadFromFile()
    {
        ifstream iStream("file.ext", ios::binary);
        if (!iStream)
        {
            cout << "No file";
        } else {
            fileHeader_t fHeader;
            iStream.read((char*)&fHeader, sizeof(fileHeader_t));
            if (fHeader.magicNumber = 0xDEADBEAF)
            {
                appointments.resize(fHeader.appointmentCount);
                iStream.read((char*)&appointments[0], fHeader.appointmentCount * sizeof(appointment));
            }
        }
    }
    void saveToFile()
    {
        ofstream oStream("file.ext", ios::binary);
        fileHeader_t fHeader;
        fHeader.magicNumber = 0xDEADBEAF;
        fHeader.appointmentCount = appointments.size();
        oStream.write((char*)&fHeader, sizeof(fileHeader_t));
        oStream.write((char*)&appointments[0], sizeof(appointment) * appointments.size());
    }
    //vector<appointment> appointments;
private:
    vector<appointment> appointments;
    string calCurrentDate;
    string calCurrentTime;
    typedef struct fileHeader_s
    {
        DWORD magicNumber;
        size_t appointmentCount;
    }fileHeader_t;
};

我越来越thew调用loadFromFile()方法时,下面的错误。

[BCC32警告] File1.cpp(185):W8060赋值可能不正确[ILINK32错误]错误:无法解析的外部 '任命::约会()' 从\ PROFILES.SOIT.LOCAL \ HOMES $ \ SIMON.CANNING \ MY DOCUMENTS引用\ RAD STUDIO \ PROJECTS \ DEBUG \ file1.obj和[ILINK32错误]错误:无法进行链路

我明白,这是因为构造函数调用的。 我可以请有关于如何解决此问题的一些建议吗?

Answer 1:

与所有的电视剧,你可能得到提振编译,然后将所有你必须做的实现序列化的废话,我个人不打扰。

只需设置大小为你的头,把它写出来的文件,然后写出你的向量的字节。

装载时,在标题读出,调整载体,它说什么,然后在载体中的字节读取。

[编辑]

正如在评论中讨论的那样,你必须意识到,你不能写出来的其他非平凡的类型(如字符串)为二进制无论是。 所有这些必须序列化。 我曾推测,从你提出你的问题的方式,你已经意识到了这一点。

所以,如果你只需要序列几个类型,并且尚未使用升压,我个人认为,使用升压解决这一问题将是矫枉过正。 人们似乎有负面回应中,我表达了这样的意见的方式,所以也许他们从来没有处理情况:有人内置升压序列化的依赖,解决一个非常简单的和孤立的问题项目=)

你真正需要的是,你可以自己编写简单的支持功能屈指可数。 你甚至不真的需要这个头包含在这种情况下,矢量大小,因为你可以序列化...

// This writes a vector of trivial data types.
template <class T>
void WriteTrivial( std::ostream& s, const std::vector<T>& data )
{
    unsigned int len = data.size();
    s.write( (char*)&len, sizeof(len) );
    s.write( (const char*)&data[0], len * sizeof(T) );
}

// This reads a vector of trivial data types.
template <class T>
void ReadTrivial( std::istream& s, std::vector<T>& data )
{
    unsigned int len = 0;
    s.read( (char*)&len, sizeof(len) );
    data.resize(len);
    if( len > 0 ) s.read( (char*)&data[0], len * sizeof(T) );
}

如果您的载体可能包含字符串或向量,则需要几个支持功能

// This writes a vector of non-trivial data types.
template <class T>
void Write( std::ostream& s, const std::vector<T>& data )
{
    unsigned int len = data.size();
    s.write( (char*)&len, sizeof(len) );
    for( unsigned int i = 0; i < len; i++ ) {
        Write( s, data[i] );
    }
}

// This reads a vector of non-trivial data types.
template <class T>
void Read( std::istream& s, std::vector<T>& data )
{
    unsigned int len = 0;
    s.read( (char*)&len, sizeof(len) );
    data.resize(len);
    for( unsigned int i = 0; i < len; i++ ) {
        Read( s, data[i] );
    }
 }

当然,与上面的你需要的东西的字符串,和读/写模板来处理正常的数据类型。 这应该让你反正开始。 希望帮助。

[编辑]

现在,您已经张贴你的代码,我的建议是:

日历

void loadFromFile()
{
    ifstream iStream("file.ext", ios::binary);
    if (!iStream)
    {
        cout << "No file";
    } else {
        fileHeader_t fHeader;
        iStream.read((char*)&fHeader, sizeof(fileHeader_t));
        if (fHeader.magicNumber != 0xDEADBEAF) return;
        appointments.resize(fHeader.appointmentCount);
        for( size_t i = 0; i < appointments.size(); i++ ) {            
            appointments[i].read(iStream);
        }
        iStream.close();
    }
}

void saveToFile()
{
    ofstream oStream("file.ext", ios::binary);
    fileHeader_t fHeader;
    fHeader.magicNumber = 0xDEADBEAF;
    fHeader.appointmentCount = appointments.size();
    oStream.write((char*)&fHeader, sizeof(fileHeader_t));
    for( size_t i = 0; i < appointments.size(); i++ ) {            
        appointments[i].write(oStream);
    }
    oStream.close();
}

现在,连载字符串:

void write( ostream &s, const string& str )
{
    unsigned int len = str.size();
    s.write((char*)&len, sizeof(len));
    s.write(str.c_str(), len*sizeof(char));
}

void read( istream &s, string& str )
{
    unsigned int len = 0;
    s.read((char*)&len, sizeof(len));
    str.resize(len);
    if( len == 0 ) return;
    s.read((char *) str.c_str(), len*sizeof(char));
}

也许写琐碎类型的一个有用的包装:

template <class T>
void writeTrivial( ostream& s, const T& val )
{
    ostream.write( (const char*)&val, sizeof(T) );
}

template <class T>
void readTrivial( ostream& s, T& val )
{
    ostream.read( (char*)&val, sizeof(T) );
}

最后,在约会

void write( ostream& s )
{
    writeTrivial(s, appDateTime);
    writeTrivial(s, appReminderDateTime);
    write(s, appType);
    write(s, appLocation);
    write(s, appComments);
    writeTrivial(s, appIsImportant);
}

void read( istream& s )
{
    readTrivial(s, appDateTime);
    readTrivial(s, appReminderDateTime);
    read(s, appType);
    read(s, appLocation);
    read(s, appComments);
    readTrivial(s, appIsImportant);
}


Answer 2:

是serilization更好的方式来做到这一点?

如果是这样,我需要使用Boost库,还是另辟蹊径?

我想你会关闭使用序列化库更好。 您使用的库可能会在这一点上是有限的,但如果你的应用程序的增长......在C ++中间件作家是上线替代传统的序列化库。



文章来源: Loading and Saving vectors to a file