目录
1. 流是什么
2. C++IO流
2.1 C++标准IO流
2.2 C++文件IO流
2.2.1 简单读取文件流
2.2.2 C++读取文件巧妙之处
3. stringstream的简单介绍
它的特性是:有序连续、具有方向性
在使用时候必须要包含文件并引入std标准命名空间 。
class Date
{
friend ostream& operator << (ostream& out, const Date& d);
friend istream& operator >> (istream& in, Date& d);
public:
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{}
operator bool()
{
// 这里是随意写的,假设输入_year为0,则结束
if (_year == 0)
return false;
else
return true;
}
private:
int _year;
int _month;
int _day;
};
istream& operator >> (istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
ostream& operator << (ostream& out, const Date& d)
{
out << d._year << " " << d._month << " " << d._day;
return out;
}
istream& operator>> (int& val);
explicit operator bool() const;
如果仅仅是为了实现上图的文件读取,C语言也很容易做到,那么C++为什么要引入IO流呢?
再展示一个比较有意思的用例了解二进制读写和文本读写:
class Date{...};
istream& operator >> (istream& in, Date& d){...}
ostream& operator << (ostream& out, const Date& d){...}
struct ServerInfo
{
//char _address[32];
string _address;
int _port;
Date _date;
};
// 二进制读写:在内存如何存储,就如何写到磁盘文件
// 优点:快 缺点:写出去内容看不见
// 文本读写:对象数据序列化字符串写出来,读回来也是字符串,反序列化转成对象数据
// 优点:可以看见写出去是什么 缺点:存在一个转换过程,要慢一些
struct ConfigManager
{
public:
ConfigManager(const char* filename = "server.config")
:_filename(filename)
{}
//二进制写
void WriteBin(const ServerInfo& info)
{
ofstream ofs(_filename, ios_base::out | ios_base::binary);
ofs.write((char*)&info, sizeof(info));
}
//二进制读
void ReadBin(ServerInfo& info)
{
ifstream ifs(_filename, ios_base::in | ios_base::binary);
ifs.read((char*)&info, sizeof(info));
}
//文本写
void WriteText(const ServerInfo& info)
{
ofstream ofs(_filename, ios_base::out);
ofs << info._address << endl;
ofs << info._port << endl;
ofs << info._date << endl;
}
//文本读
void ReadText(ServerInfo& info)
{
ifstream ifs(_filename, ios_base::in);
ifs >> info._address >> info._port >> info._date;
}
private:
string _filename; // 配置文件
};
int main()
{
//二进制写出去
ServerInfo winfo = { "127.0.0.1", 888 };
ServerInfo winfo = { "https://legacy.cplusplus.com/reference/istream/istream/read/", 888, { 2022, 11, 30 } };
ConfigManager cm;
cm.WriteBin(winfo);
// 二进制的读
ServerInfo rinfo;
ConfigManager cm;
cm.ReadBin(rinfo);
cout << rinfo._address << endl;
cout << rinfo._port << endl;
//文本写出去
ServerInfo winfo = { "127.0.0.1", 888};
ServerInfo winfo = { "https://legacy.cplusplus.com/reference/istream/istream/read/", 888, { 2022, 11, 30 } };
ConfigManager cm;
cm.WriteText(winfo);
// 文本的读
ServerInfo rinfo;
ConfigManager cm;
cm.ReadText(rinfo);
cout << rinfo._address << endl;
cout << rinfo._port << endl;
cout << rinfo._date << endl;
return 0;
}
int main()
{
stringstream sstream;
// 将多个字符串放入 sstream 中
sstream << "first" << " " << "string,";
sstream << " second string";
cout << "strResult is: " << sstream.str() << endl;
// 清空 sstream
sstream.str("");
sstream << "third string";
cout << "After clear, strResult is: " << sstream.str() << endl;
return 0;
}
2. 序列化和反序列化结构数据
struct ChatInfo
{
string _name; // 名字
int _id; // id
Date _date; // 时间
string _msg; // 聊天信息
};
int main()
{
// 序列化
ChatInfo winfo = { "张三", 135246, { 2022, 4, 10 }, "晚上一起看电影吧" };
//ostringstream oss;
stringstream oss;
oss << winfo._name << endl;
oss << winfo._id << endl;
oss << winfo._date << endl;
oss << winfo._msg << endl;
string str = oss.str();
cout << str << endl;
// 反序列化
ChatInfo rInfo;
//istringstream iss(str);
stringstream iss(str);
iss >> rInfo._name;
iss >> rInfo._id;
iss >> rInfo._date;
iss >> rInfo._msg;
cout << "----------------------------------" << endl;
cout << rInfo._date << endl;
cout << rInfo._name << "[" << rInfo._id << "]:>" << rInfo._msg << endl;
cout << "----------------------------------" << endl;
return 0;
}