cin和cout是与终端的交互。cpp的I\O流,还能对文件和内存进行操作。
文件操作主要使用了3个类模版:basic_ifstream输入, basic_ofstream输出, basic_fstream打开一个文件,同时接受输入和输出2种操作。
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
std::ofstream outFile("Myfile");
outFile << "Jammy & Kin !\n";
}
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
std::ofstream outFile;
cout << outFile.is_open() << endl; // 0
outFile.open("Myfile");
cout << outFile.is_open() << endl; // 1
outFile.close();
cout << outFile.is_open() << endl; // 0
}
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
std::ofstream outFile;
cout << outFile.is_open() << endl; // 0
outFile.open("Myfile");
outFile << "Jammy!\n"; // 系统已开始不写到文件里,而是写到缓存里
outFile.close(); // close时,系统将缓存的内容放到文件里
// 如果没有close,系统会根据机制,自动关闭。我们一般构造一个语句体(域),让它自动销毁
std::ifstream inFile("Myfile"); // 文件名称
std::string x;
inFile >> x; // 等待x的输入
cout << x << endl; // 将x的内容打到终端里
}
通常in和out打开文件,光标都是在最开头。ate就是让光标放在最后。
ate和app不一样的地方是,ate开始在文件末尾,可以移动到文件当中某一个位置。app只能放在文件的末尾,不同移到中间。
trunc: 打开文件是用来写的,并且把文件之前的内容删除掉。
binary: 能禁止系统特定的转换。
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
// 把文件之前的内容删除,添加新的内容
std::ofstream outFile("Myfile", std::ios_base::out | std::ios_base::trunc);
outFile << "Hello World";
}
basic_istringsteam: 读取数据
basic_ostringstream: 写入数据
basic_stringstream: 读写
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
std::ostringstream obj1;
obj1 << 1234; // obj1内存流对象,把1234整数写入,将整数转成了字符串
auto res = obj1.str(); // res获取底层对应的内存,res类型是std::string
cout << res << endl; // 1234,注意这里已经不是上面的1234整数了,而是一个字符串
}
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
std::ostringstream obj1;
obj1 << 10;
std::string res = obj1.str();
std::istringstream obj2(res); //构造输入流,把读取的res内存读出来
int x;
obj2 >> x;
cout << x << endl; // 10 obj2从res读取1和0,在内部完成解析,将1和0解析,然后存在int x中,输出
}
内存流也会受到打开流的影响,但是没有trunc和binary。
int main()
{
std::ostringstream buf2("test", std::ios_base::ate);
buf2 << 1;
cout << buf2.str() << endl; // test1
}
int main()
{
std::ostringstream buf2("test"); // ate去掉
buf2 << 1;
cout << buf2.str() << endl; // 1est
}
int main()
{
std::ostringstream buf2("test", std::ios_base::app);
buf2 << 1;
cout << buf2.str() << endl; // test1 str返回是cpp类型的字符串
}
基于字符串流的字符串拼接优化
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
std::string x;
x += "Hello";
x += " world";
x += " Jammy";
x += " Kin";
// 这样性能比较差,先看string是否有足够的缓冲区足够保存新的字符串。
// 将原有的stirng拷贝新的缓冲区,加上新的string,再把原缓冲区释放
// 内存的不断地开辟和释放,非常耗时
cout << x << endl;
// 等价于下面的代码
std::ostringstream obj;
obj << "Hello";
obj << " world";
obj << " Jammy";
obj << " Kin";
cout << obj.str() << endl; // 基于字符串流的字符串拼接优化,缓存满了,一次性刷新
}
流的状态:正常状态,还是异常的状态。
刚开始使用流,都是正常的,但是随着插入或者提取,可能会失败,就是异常的状态。
badbit
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
std::ofstream outFile;
outFile << 10; // 流的异常状态,会产生badbit(不可恢复的流错误)
}
输入流的failbit
int main()
{
int x;
cin >> x; // 如果输入“Hello”,这样读取就失败了,cin就是failbit
}
输出流的failbit
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
std::ofstream outFile;
outFile.close(); //这里outFile本身没有关联任何文件,是关闭状态,调用close再关闭,就会产生failbit。
}
failbit是一种可以恢复的错误,不同于badbit。
eofbit:(end of file)文件末尾,无法再读取。对于内存流和终端流都是有效的。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int x;
cin >> x; // 1
cout << std::cin.good() // 1
<< std::cin.bad() // 0
<< std::cin.fail() // 0
<< std::cin.eof() // 0
<< endl;
}
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int x;
cin >> x; // abc
cout << std::cin.good() // 0
<< std::cin.bad() // 0
<< std::cin.fail() // 1
<< std::cin.eof() // 0
<< endl;
}
通常,我们不给流设置复位。clear和setstate。
流是一长串,那么往哪里进行写入和读取,这就需要流的定位。
seekg()和seekp(),都是覆盖操作,而不是插入操作。
seekg有2个方法。重载了。
flush,将缓冲区内容扔到外部设备里,将缓冲区内容清空。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
cout << "What's your name \n"; // 如果这句话没占满缓冲区,下面等待用户输入,就在缓冲区里放着
// 我们希望在等待用户输入之前,就把句子打出来
// std::endl和std::flush 都可以
cout.flush();
std::string name;
cin >> name;
}
sync可以选择清空缓冲区或者重新填充它。具体做哪个,库函数自己决定的。
unitbuf,单位缓冲区。本质含义是写入要大于等于1个字符,也就是只要写一个东西,就从缓冲区放到终端里。因为缓冲区太小了,就1个字符。好处是信息立即存入终端,坏处是效率的降低。
2个流(输入/输出)绑定到1个输出流。既可以多对一,但是不能一对多。A不可以既绑定输出流C,又绑定输出流D。
c++和c语言输入和输出函数同步,这样的同步一定是有成本的,效率一定是降低的。可以通过sync_with_stdio关闭。
因为解除了同步。