二进制读写:在内存中如何存储,就如何写到磁盘文件
优点:快 缺点:写出去内容看不见
文本读写:序列化字符串写出来,读回来也是字符串,反序列化转成对象数据
优点:可以看出来写的什么 缺点:存在一个转换过程,要慢一些
struct ServerInfo
{
//char _address[32];
string _address;
int _port;
Date _date;
};
struct ConfigManager
{
public:
ConfigManager(const char* filename)
:_filename(filename)
{}
// 二进制读写,读写对象中,不能有string
void WriteBin(const ServerInfo& info)
{
ofstream ofs(_filename, ofstream::out | ofstream::binary);
ofs.write((char*)&info, sizeof(info));
}
void ReadBin(ServerInfo& info)
{
ifstream ifs(_filename, ofstream::in | ofstream::binary);
ifs.read((char*)&info, sizeof(info));
}
// 文本读写 C++文本读写更简单
// 文本读写本质,内存中任何类型都是转成字符串在写
// c语言文本读写很不方便,因为要不断转字符串
// c++封装了以后就有很大的优势
void WriteText(const ServerInfo& info)
{
ofstream ofs(_filename);
ofs << info._address<<" ";
ofs << info._port << endl;
ofs << info._date << endl;
}
void ReadText(ServerInfo& info)
{
ifstream ifs(_filename);
ifs >> info._address;
ifs >> info._port;
ifs >> info._date;
}
private:
string _filename; // 配置文件
};
ostringstream和istringstream是C++标准库中的两个类,用于进行字符串流的输入和输出操作。
ostringstream是一个字符串输出流类,可以将各种类型的数据以字符串的形式输出到一个字符串对象中。它提供了类似于输出流的操作符<<的接口,可以用于将数据插入到字符串流中。例如,可以使用ostringstream将整数、浮点数等转换为字符串。
示例代码如下:
#include
#include
int main() {
std::ostringstream oss;
int num = 123;
float pi = 3.14159;
oss << "Number: " << num << ", Pi: " << pi;
std::string result = oss.str();
std::cout << result << std::endl;
return 0;
}
输出结果为:Number: 123, Pi: 3.14159
istringstream是一个字符串输入流类,可以从一个字符串对象中读取数据。它提供了类似于输入流的操作符>>的接口,可以用于从字符串流中提取数据。例如,可以使用istringstream从一个字符串中提取整数、浮点数等数据。
示例代码如下:
#include
#include
int main() {
std::string input = "Number: 123, Pi: 3.14159";
std::istringstream iss(input);
std::string str;
int num;
float pi;
iss >> str >> num >> str >> pi;
std::cout << "Number: " << num << ", Pi: " << pi << std::endl;
return 0;
}
输出结果为:Number: 123, Pi: 3.14159
总结来说,ostringstream用于将数据转换为字符串输出,而istringstream用于从字符串中提取数据。它们在处理字符串和数值之间的转换时非常有用。
自定义类型支持流插入流提取
要使自定义类型支持流插入和流提取操作,需要在类中重载相应的运算符。
对于流插入操作,需要重载输出流运算符<<。该运算符接受一个输出流对象和一个自定义类型对象作为参数,并将自定义类型对象的数据输出到输出流中。
示例代码如下:
#include
class MyType {
public:
MyType(int value) : m_value(value) {}
friend std::ostream& operator<<(std::ostream& os, const MyType& obj) {
os << "Value: " << obj.m_value;
return os;
}
private:
int m_value;
};
int main() {
MyType obj(123);
std::cout << obj << std::endl;
return 0;
}
输出结果为:Value: 123
对于流提取操作,需要重载输入流运算符>>。该运算符接受一个输入流对象和一个自定义类型对象的引用作为参数,并从输入流中读取数据并赋值给自定义类型对象。
示例代码如下:
#include
class MyType {
public:
MyType() : m_value(0) {}
friend std::istream& operator>>(std::istream& is, MyType& obj) {
is >> obj.m_value;
return is;
}
private:
int m_value;
};
int main() {
MyType obj;
std::cout << "Enter a value: ";
std::cin >> obj;
std::cout << "Value entered: " << obj << std::endl;
return 0;
}
运行程序后,会提示用户输入一个值,然后将输入的值赋值给自定义类型对象,并输出该值。
总结来说,要使自定义类型支持流插入和流提取操作,需要重载输出流运算符<<和输入流运算符>>。通过重载这两个运算符,可以实现自定义类型与流之间的转换。
#include
//int main()
//{
// //ostringstream oss;
// stringstream oss;
// oss << 100 << " ";
// oss << 11.22 << " ";
// oss << "hello";
//
// string str = oss.str();
// cout << str << endl;
//
// //istringstream iss(str);
// stringstream iss(str);
// int i;
// double d;
// string s;
// iss >> i >> d >> s;
// cout << i << endl;
// cout << d << endl;
// cout << s << endl;
//
// return 0;
//}
// 序列化和反序列化
struct ChatInfo
{
string _name; // 名字
int _id; // id
Date _date; // 时间
string _msg; // 聊天信息
};
int main()
{
ChatInfo winfo = { "张三", 135246, { 2022, 4, 10 }, "晚上一起看电影吧" };
stringstream oss;
oss << winfo._name << " ";
oss << winfo._id << " ";
oss << winfo._date << " ";
oss << winfo._msg;
string str = oss.str();
cout << str << endl;
stringstream iss(str);
ChatInfo rinfo;
iss >> rinfo._name;
iss >> rinfo._id;
iss >> rinfo._date;
iss >> rinfo._msg;
cout << "-------------------------------------------------------" << endl;
cout << "姓名:" << rinfo._name << "(" << rinfo._id << ") ";
cout << rinfo._date << endl;
cout << rinfo._name << ":>" << rinfo._msg << endl;
cout << "-------------------------------------------------------" << endl;
return 0;
}