IO类
C++标准库中一共有三种IO类,输入输出(iostream),文件输入输出(fstream),字符串输入输出(sstream),具体类型如下,其中以w开头的类型是宽字符版本,sstream和fstream继承自iostream,所以这些类型之间有着共同的特性。
| 类型 | 头文件 |
|---|---|
| istream,wistream从流读取数据 | iostream |
| ostream,wostream向流写入数据 | iostream |
| iostream,wiostream读写流 | iostream |
| ifstream,wifstream从文件读取数据 | fstream |
| ofstream,wofstream向文件写入数据 | fstream |
| fstream,wfstream读写文件 | fstream |
| istringstream,wistringstream从string读取数据 | sstream |
| ostringstream,wostringstream向string写入数据 | sstream |
| stringstream,wstringstream读写string | sstream |
常见IO对象
- cin,一个istream对象,从标准输入读取数据。
- cout,一个ostream对象,从标准输出写入数据。
- cerr,一个ostream对象,用于输出错误消息。
- getline函数,从一个给定的输入流读取一行数据存入string对象。
IO对象无拷贝或赋值
int main(void)
{
std::ofstream out1, out2;
std::ofstream out3 = out1;//错误,无法使用拷贝初始化
out1 = out2;//错误,无法使用拷贝赋值运算符
system("pause");
return 0;
IO对象状态
IO操作有可能发生错误,有些错误是可恢复的,有些错误则不能恢复,下面函数可以帮助我们访问和设置IO对象的状态,其中badbit置位表示发生了系统级错误,无法恢复;failbit置位表示虽然IO操作出现了问题,但是这种问题是可以修正的,流还可以继续使用;如果到达文件结束,则eofbit和failbit都会被置位;如果badbit,failbit,eofbit任意一个被置位了,则检测流状态的条件都会失败。
| 函数 | 描述 |
|---|---|
| eof() | 若流的eofbit置位,则返回true,表示流到达了文件结束 |
| fail() | 若流的failbit或badbit置位,则返回true,表示IO操作失败了 |
| bad() | 若流的badbit置位,则返回true,表示发生了系统级错误,无法恢复 |
| good() | 若流处于有效状态,则返回true |
| clear() | 将流的所有状态位复位,将流的状态设置为有效 |
| clear(flags) | 根据给定的标志位,将流对应的状态位复位 |
| setstate(flags) | 根据给定的标志位,将流对应的状态位置位 |
| rdstate() | 返回流当前的状态 |
static constexpr _Iostate goodbit = (_Iostate)0x0;
static constexpr _Iostate eofbit = (_Iostate)0x1;
static constexpr _Iostate failbit = (_Iostate)0x2;
static constexpr _Iostate badbit = (_Iostate)0x4;
下面代码中,当输入数据不能转换为int时读操作就会失败,cin的failbit就会置位。
int main(void)
{
int intValue;
while (true)
{
if (std::cin >> intValue) {
std::cout << "输入正确:" << std::cin.rdstate() << std::endl;
}else {
std::cout << "输入错误:"<< std::cin.rdstate() << std::endl;
break;
}
}
std::cout << "failbit:" << std::ios_base::failbit << std::endl;
system("pause");
return 0;
}
1
输入正确:0
b
输入错误:2
管理输出缓冲
每个输出流都管理一个缓冲区,缓冲区的存在可以使多次写操作合并为一次,从而提高性能,只有在缓冲区刷新的时候才真正的写到设备或文件。下列情况下缓冲区被刷新:
- 程序正常结束时,缓冲区被刷新。
- 缓冲区满时,缓冲区被刷新。
- 可以使用操纵符例如endl显式刷新缓冲区。
int main(void)
{
std::cout << "hello,world" << std::endl;//输出hello,world和一个换行,然后刷新缓冲区
std::cout << "hello,world" << std::flush;//输出hello,world,然后刷新缓冲区
std::cout << "hello,world" << std::ends;//输出hello,world和一个空字符,然后刷新缓冲区
system("pause");
return 0;
}
- 可以使用操纵符unitbuf设置流的内部状态,使任何输出都立即刷新,无缓冲。
int main(void)
{
std::cout << std::unitbuf;//所有输出操作立即刷新缓冲区
std::cout << "hello,world";
std::cout << std::nounitbuf;//回到正常的缓冲方式
system("pause");
return 0;
}
- 当一个输入流被关联到一个输出流的时候,任何试图从输入流读取数据的操作都会先刷新关联的输出流,例如cin和cout。
int main(void)
{
std::ostream* out1 = std::cin.tie();//获取cin关联的输出流
*out1 << out1 << std::endl;
std::cin.tie(out1);//关联cin和cout
system("pause");
return 0;
}