加载和保存矢量到文件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加载和保存矢量到文件相关的知识,希望对你有一定的参考价值。
我正在使用C ++ Builder,我有一个Appointment
对象的向量数组。
我想将其保存到文件并加载它。
目前,我使用ifstream和ofstream与二进制文件。我有一个标题,其中包含将与数据一起保存的向量大小,以便在加载时知道其大小。
灭菌是一种更好的方法吗?
如果是这样,我是否需要使用升级库或其他方式?
这是我目前的代码:
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;
};
调用loadFromFile()方法时,我遇到了以下错误。
[BCC32警告] File1.cpp(185):W8060可能不正确的分配[ILINK32错误]错误:未解析的外部'预约::约会()'引自 PROFILES.SOIT.LOCAL HOMES $ SIMON.CANNING MY DOCUMENTS RAD STUDIO PROJECTS DEBUG FILE1.OBJ [ILINK32错误]错误:无法执行链接
我知道这是因为构造函数调用而发生的。我可以就如何解决这个问题提出一些建议吗?
有了所有的戏剧你可能会得到提升编译,然后你需要做的所有guff实现序列化,我个人不打扰。
只需将大小设置到标题中,将其写入文件,然后写出向量的字节。
加载时,读入标题,将向量调整为它所说的大小,然后读入向量的字节。
[编辑]
正如评论中所讨论的那样,您必须意识到您不能将其他非平凡类型(例如字符串)写为二进制。所有这些都必须序列化。从你提出问题的方式来看,我已经推断出你已经意识到了这一点。
因此,如果你只需要序列化几种类型并且还没有使用boost,我个人认为使用boost来解决这个问题将是过度的。人们似乎对我表达这种观点的方式做出了负面反应,所以也许他们从来没有必要处理一个项目,在这个项目中,有人建立了依赖于boost序列化以解决一个非常简单和孤立的问题=)
您真正需要的是一些简单的支持功能,您可以自己编写。在这种情况下,您甚至不需要该标头来包含矢量大小,因为您可以序列化...
// 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);
}
灭菌是一种更好的方法吗?
如果是这样,我是否需要使用升级库或其他方式?
我认为你最好使用序列化库。此时您对库的使用可能会受到限制,但如果您的应用程序增长... C++ Middleware Writer是传统序列化库的替代品。
以上是关于加载和保存矢量到文件的主要内容,如果未能解决你的问题,请参考以下文章