文章目录
- 1.流的状态
- 2.流的定位
- 3.流的同步
1.流的状态
- 流的状态:流的状态都是位掩码类型,如果
iostate
是char类型,那么可能的定义如下: - 流的状态举例:
// 1.badbit:不可恢复的错误
std::ofstream outFile;
outFile << 10; // 没有关联文件,bagbit错误
// 2.failbit:输入输出操作失败(格式化或提取错误),可恢复
int x;
std::cin >> x; // 如果终端输入hello,由于想要的是int,输入是字符串,所以失败
// 3.eofbit:关联的输入序列已抵达文件尾
int x;
std::cin >> x; // 终端输入ctrl+d,表示输入结束
- 检测流的状态:见下图。其中需要注意的有几点:
-
good
状态只有在所有的标志位都没有置位的时候才是true - 只要
bad
状态是true
,那么fail
状态一定是true
,这个也很好理解,因为bad
状态的严重程度比fail
更强,所以是bad
一定是fail
。 - 只要
failbit/badbit
没有置位,即使eofbit
置位了,那么把流状态转化成bool
值的结果也是true
,因为经常写下面的代码,这个时候即使eofbit
置位了,但是也是成功读取了,所以流的状态是正常的。
- 复位流的状态
2.流的定位
- 获取流的位置:注意
tellg
,g
就是get
,所以是获取输入流的位置;tellp
,p
就是put
,所以是获取输出流的位置。返回的结果是pos_type
类型,但是这个类型到底是int
还是long
等没有明确的定义,但是他一定是一个整数。
tellg
实例:tellp
实例:
- 设置流的位置:
- 注意对于输出流来说,移动了流的位置之后,会对后面的内容进行覆盖,而不是插入。
- 为什么输入流和输出流还要用
g
和p
来区分输入输出的位置?这是因为对于普通的fstream/stringstream
来说,既可以输入也可以输出,那么他就包含输入位置、输出位置两个,所以要使用两个g/p
来标识输入/输出的位置。 - 设置流的位置有两种重载的方式,一种是绝对位置,一种是相对位置:
3.流的同步
- 对于输出流的
flush
同步,有两种方法:一个是std::flush
,这个是一个操作符,和std::endl
类似。另一个是std::baisc_iostream::flush
,这个则是iostream
的一个方法。所以二者使用方式是不同的,如下所示:
// 使用操作符刷新输出流
std::cout << "hello" << std::flush;
// 使用类 的方法刷新输出流
std::cout << "hello";
std::cout.flush();
输入流
sync()
同步的使用较少,可以不用特别关注。- 使用
unitbuf
操作符可以实现每次输出后自动同步,从字面上理解这个操作符就是把输出流的缓冲区大小设置成1,所以这样只要一往缓冲区写入内容就会输出。如下所示: - 另外:关于
cout
和cerr
的一个区别就是,cout
默认有缓冲区,因为他是标准输出,信息没有那么重要;而cerr
默认没有缓冲区,也就是设置成了unitbuf
,因为它是标准错误输出,信息非常重要,一旦有错误就要及时输出。 基于绑定的同步:这样的好处是在操作流的时候会刷新它绑定的输出流,从而保证输出流的内容可以被显示。比如如下的例子,
cin
绑定到了cout
上,在调用cin
之前,就可以保证cout
的缓冲区一定可以被刷新,也就是内容一定可以显示。
std::cout << "What't you name?\n";
std::string name;
std::cin >> name;
- C++和C语言的IO同步