1. “流” 的目的与本质
流的目的是为了解耦。
1.1 “耦合 / Coupling ”是什么?
事物之间存在不必要的关系,就叫耦合;这种关系往往会引发双方进一步产生额外的牵制关系。
1.2 “流”解的是谁和谁的耦合?
以“面对面”的方式(有时还加上“一对一”的关系)进行数据交接的双方,很容易产生时间、地点、方式上的耦合。
以生活中的事情为例,假设要求快递一定要将货物面对面的交给买家,甚至要求买家签字(其实,最早的快递,基本就是如此),那么,就至少有如下耦合:
- 时间耦合:不是你等快递员,就是快递员等你;
- 地点耦合:收货地点是公司,可是今天你请假在家;收货地点是家,可是今天你996;
- 方式耦合:不仅要当面交接,如买家因种种原因拒签,则容易引发双方纠纷;
程序中的数据交接,如果也只能走“面对面”这一种形式,同样容易引发各种耦合。因此,想要解除或降低A和B之间因数据交接产生的耦合,方法是在二者之间塞入一个第三方:数据缓存区。这各现实上快递和收货人之间的解耦的本质是一样:东西放在楼下小店、放在菜鸟驻站、放在丰巢……
1.3 🎞️视频一:“流” 的基本概念
1.4 流的本质是队列
学完视频之后,我们了解到以下几点:
- 流的本质是队列,即:一个带有顺序保障的数据缓存区;
- 依据程序的视角,流区分为输入流和输出流;
- 向程序输入数据的流,叫输入流;程序向之输出数据的流,叫输出流;
- “ostream” 代表抽象的、泛指的输出流,文件输出流 “ofstream”和字符串输出流 “ostringstream” 都是输出流;
- “istream” 代表抽象的,泛指的输入流,文件输入流“ifstream”和字符串输入流“istringstream”都是输入流;
- 文件流可视为“外存流”,具有外存的特点:可理解为永久存储,但读写较慢;
- 字符串流可视为“内存流”,具有内存的特点:不能永远存储,但读写更快;
- 如上所述,文件流和内存流都可以既是输入流,也是输出流。
2. 面向抽象流的编程实例
请观看视频二,相关代码见后。
2.1 🎞️视频二:日志输出的5个版本
2.2 版本1:手工写日志
#include <iostream>
using namespace std;
int main()
{
cout << "【信息】:" << "即将输出你好世界!" << endl;
cout<<"你好,世界!" << endl;
cout << "【信息】:" << "完成输出你好世界!" << endl;
cout << "【信息】:" << "终于不辱使命,即将全身而退。" << endl;
}
2.3 版本2:使用函数写日志
#include <iostream>
#include <string>
using namespace std;
void OutputDebugInfo(std::string const& debug_info)
{
cout << "【信息】:" << debug_info << endl;
}
int main()
{
OutputDebugInfo("即将输出你好世界!");
cout<<"你好,世界!" << endl;
OutputDebugInfo("完成输出你好世界!");
OutputDebugInfo("终于不辱使命,即将全身而退。");
}
2.4 版本3:使用文件输出流
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void OutputDebugInfo(ofstream& ofs, std::string const& debug_info)
{
ofs << "【信息】:" << debug_info << endl;
}
int main()
{
ofstream ofs ("log.txt");
OutputDebugInfo(ofs, "即将输出你好世界!");
cout<<"你好,世界!" << endl;
OutputDebugInfo(ofs, "完成输出你好世界!");
OutputDebugInfo(ofs, "终于不辱使命,即将全身而退。");
}
2.5 版本4:使用抽象输出流
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void OutputDebugInfo(ostream& os, std::string const& debug_info)
{
os << "【信息】:" << debug_info << endl;
}
int main()
{
ofstream ofs ("log.txt");
OutputDebugInfo(ofs, "即将输出你好世界!");
cout<<"你好,世界!" << endl;
OutputDebugInfo(ofs, "完成输出你好世界!");
OutputDebugInfo(cout, "终于不辱使命,即将全身而退。");
}
2.6 版本5:使用字符串流
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
void OutputDebugInfo(ostream& os, std::string const& debug_info)
{
os << "【信息】:" << debug_info << endl;
}
int main()
{
ofstream ofs ("log.txt");
OutputDebugInfo(ofs, "即将输出你好世界!");
cout<<"你好,世界!" << endl;
ostringstream oss;
OutputDebugInfo(oss, "估计要出错了哦……");
OutputDebugInfo(oss, "好像还真的是出错了!");
OutputDebugInfo(oss, "原来,并没有出错啊");
cout << oss.str() << endl;
OutputDebugInfo(ofs, "完成输出你好世界!");
OutputDebugInfo(cout, "终于不辱使命,即将全身而退。");
}