1、基类 istream 和 ostream
(1)istream
A.What
输入流的抽象类,是所有输入流类的基类
B.Why(输入流的作用)
用于从数据源(如文件、标准输入设备等)读取数据
(2)ostream
A.What
输出流的抽象类,是所有输出流类的基类
B.Why(输出流的作用)
输出流用于将数据写入到目标位置,例如文件或标准输出设备(通常是屏幕)
(3)输入输出流的状态
A.Which
goodbit:表示流处于正常状态,可以进行正常的输入和输出
eofbit:表示已经到达文件末尾或流的结束位置,当文件读取完毕时,eofbit会被设置为1
failbit:表示流操作失败,如尝试将字符写入只读文件、尝试从空文件中读取数据
badbit:表示流已经崩溃或数据出现问题,如打开不存在的文件、内存不足等
stream.good();
stream.eof();
stream.fail();
stream.bad();
B.How(如何操作流状态)
获取流的状态:stream.rdstate()
if(istream.rdstate() & std::ios_base::badbit)
{ std::cout<<"badbit error!"<<std::endl;
}
复位流状态位:goodbit设置为1,其它设置为0
istream.clear();
设置指定状态位:但 stream.setstate(goodbit)不合法
istream.setstate(std::ios_base::failbit | std::ios_base::eofbit);
2、派生类fstream
(1)fstream
A.What
C++ 标准库中用于文件输入输出操作的文件流类
B.Why
实现对文件的输入和输出操作
C.文件打开方式
模式 | 说明 |
---|---|
in | 以读的方式打开文件 |
out | 以写的方式打开文件,写数据后原文件将被覆盖 |
out | trunc | 当以 trunc 模式打开文件时,如果该文件存在, 则先清空,后写入新数据。如果文件不存在,则创建 |
out | app | 每次写操作均定位到文件末尾 |
binary | 二进制形式打开文件(in&out) |
ate | 打开文件后立即定位到文件末尾(in&out) |
(2)ifstream
A.What
文件输入流类,是istream的派生类
B.Why
用于实现从文件中读取数据
C.How
std::string strFilePth = "D:\\Desktop\\a.txt";
// 以读的方式打开文件
std::ifstream inStream;
inStream.open(strFilePth);
if (!inStream.is_open())
{std::cerr << "Failed to open file" << std::endl;return;
}
char ch[10];
while (inStream.read(ch, 10))
{std::cout << ch << std::endl;
}
inStream.close();
(3)ofstream
A.What
文件输出流类,是ostream的派生类
B.Why
用于向文件中写入数据
C.How
std::string strFilePth = "D:\\Desktop\\a.txt";
// 以写的方式打开文件
std::ofstream outStream;
outStream.open("D:\\Desktop\\a.txt", std::ios_base::app);
if (!outStream.is_open())
{std::cerr << "Failed to open file" << std::endl;return;
}
// 向文件中写入数据
int i = 0;
while (!outStream.eof())
{outStream << "wodeshijie" << std::endl;++i;if (i >= 10){outStream.setstate(std::ios_base::eofbit);}
}
outStream.close();
3、流缓冲
(1)What(什么是流缓冲)
本质是一个内存中的缓冲区,每个输入或输出流对象都管理一个缓冲区,用来保护读写数据
(2)刷新缓冲
将数据真正写入到文件或输出设备中
(3)When(什么时候刷新缓冲)
- 程序正常结束时
- 缓冲区满时
- 使用操作符endl、ends、flush时:flush表示主动刷新缓冲区
- 一个流关联到另一个流时:
如默认情况下 cin 和 cerr 都关联到 cout,因此读 cin 或写 cerr 都会导致 cout 的缓冲区被刷新
4、格式化输入和输出
(1)What
标准库定义了一组操纵符(本质是函数或对象)来修改流的格式状态 当操作符改变流的格式状态时,通常改变后的状态对所有后续 IO 都生效
(2)Which
A.控制布尔值的格式
bool bFlag = true;
std::cout<<std::boolalpha<<bFlag<<std::endl; //打印:true
std::cout<<std::noboolalpha<<bFlag<<std::endl; //打印:1
B.控制整型值进制的格式
cout<<"default:"<<20<<" "<<1024<<endl;
cout<<"octal:"<<oct<<20<<" "<<1024<<endl;
cout<<"hex:"<<hex<<20<<" "<<1024<<endl;
cout<<"decimal:"<<dec<<20<<" "<<1024<<endl;
输出结果:
default:20 1024
octal:24 2000
hex:14 400
decimal:20 1024
C.控制浮点数的格式
// 浮点数格式
double a = 12.123456789;
cout << cout.precision() << endl; // 打印:6 (默认精度为 6)
cout << a << endl; // 打印:12.1235
// 浮点数精度设置——precision
cout.precision(12); cout << a << endl; // 打印:12.123456789
// 是否显式为 0 的小数——showpoint noshowpoint(默认) double b = 12.000000;
cout << b << endl; // 打印:12
cout << std::showpoint << b << endl; // 打印:12.000000
// 科学计数格式——scientific
double c = 123456.123456;
cout << std::scientific << c << endl; // 打印:1.234561234560e+05
4、非格式化输入和输出
(1)What
主要是使用流对象函数实现输入和输出
(2)单字节操作
char ch; while (cin.get(ch))
{
cout.put(ch); }int ch;
while ((ch = cin.get()) != EOF)
{
}
cout.put(ch)
(3)多字节操作
// 输入流对象函数使用:get(char_arr,max_len,delim)
instream.clear();
cout << instream.tellg() << endl; // 打印:247
instream.seekg(0, std::ios::beg); // 设置流的当前指针
cout << instream.tellg() << endl; // 打印:0
const int MAX_LEN = 1000; char wch[MAX_LEN]; // 应该比读取的最大长度要大
instream.get(wch, MAX_LEN, '\0'); // 读取最大长度为 MAX_LEN 的字符
cout << wch << endl; // 打印:所有文本
// 输入流对象函数使用:getline(char_arr,max_len,delim)
instream.clear();
instream.seekg(0, std::ios::beg);
char ch_arr02[MAX_LEN];
instream.getline(ch_arr02, MAX_LEN, '\0');
cout << ch_arr02 << endl;
// 输入流对象函数使用:read (char_arr,max_len)
instream.clear();
instream.seekg(0, std::ios::beg);
char ch_arr03[MAX_LEN];
instream.read(ch_arr03, MAX_LEN / 5);
cout << instream.gcount() << endl; // 打印:200
cout << instream.tellg() << endl; // 打印:208
cout << ch_arr03 << endl;
(4)流的随机访问
instream.clear(); instream.seekg(0, std::ios::beg);
for (int i = 0; i < MAX_LEN; ++i) {instream >> std::noskipws >> ch; if (instream.fail()) break;instream.seekg(i); cout << ch;
}