一、IO类
c++不直接处理输入和输出,而是通过标准库中的类型处理IO。C++ 的 I/O(输入/输出)库主要包含在 < iostream >、< fstream >、< sstream > 等头文件中。这些库提供了丰富的功能,用于在控制台、文件、字符串等之间进行数据的输入和输出。
- iostream头文件
类型 | 作用 |
---|---|
istream(宽字符为wistream) | 从流读取数据 |
ostream (宽字符为wostream) | 向流写入数据 |
iostream(宽字符为wiostream) | 读写流 |
- fstream头文件
类型 | 作用 |
---|---|
ifstream(宽字符版本wifstream) | 从文件读取数据。 |
ofstream (宽字符版本wofstream) | 向文件写入数据 |
fstream(宽字符版本wfstream) | 读写文件 |
- sstream头文件
类型 | 作用 |
---|---|
istringstream(宽字符版本wistringstream) | 从string读取数据 |
ostringstream (宽字符版本wostringstream) | 向string写入数据 |
stringstream(宽字符版本wstringstream) | 读写string |
1、IO对象无拷贝和赋值
C++ 的 I/O 对象(如 std::cin、std::cout、文件流对象等)通常不支持拷贝构造函数
和拷贝赋值操作符
,这是因为这些对象通常代表与特定资源(如控制台、文件等)的关联,而这些资源通常不能简单地被复制。
ofstream out1, out2;
out1 = out2;
//错误:IO类不能进行赋值操作
ofstream print(ofstream);
//错误:I/O流对象不应该被复制或返回,可能会导致资源泄露。
out2 = print(out2)
//错误:不能拷贝流对象
如果你想在多个地方使用相同的 I/O 功能,你通常应该传递对 I/O 对象的引用
,而不是试图复制它们。
void processFile(std::ifstream& file)
{
std::string line;
while (std::getline(file, line))
{
// 处理每一行
std::cout << line << std::endl;
}
}
2、条件状态
在C++中,I/O流类(如istream、ostream、fstream、ifstream、ofstream等)都包含条件状态,用于表示流的状态。
这些状态指示了流的当前情况,例如是否遇到了输入/输出错误、是否到达文件末尾(EOF)等。
方法 | 作用 |
---|---|
strm::iostat | 是一种类型,提供了表达条件状态的完整功能 |
strm::badbit | 用来指出流已经崩溃 |
strm::failbi | 用来指出一个IO操作失败 |
strm::eofbit | 用来指出流到达了文件结束 |
strm::goodbi | 用来指出流未处于错误状态,此值保证为零 |
s.eof() | 若流s的eofbit置位,则返回true |
s.fail() | 若流s的failbit置位,则返回`true |
s.bad() | 若流s的badbit置位,则返回true |
s.good() | 若流s处于有效状态(即没有failbit、badbit或eofbit置位),则返回true |
s.clear() | 将流s中所有条件状态位复位,将流s的状态设置成有效,返回void |
s.clear(flags) | 根据给定的flags标志位,将流s中对应条件状态位复位。flags类型为strm::iostate。返回void |
s.setstate(flags) | 根据给定的标志位flags,将流s中对应的条件状态位置位,表示发生了错误。flags类型为strm::iostate。返回void |
s.rdstate() | 返回流s的当前条件状态,返回值类型为strm::iostate |
3、查询和管理流的状态
#include <iostream>
#include <fstream>
int main() {
// 尝试打开一个不存在的文件
std::ifstream file("a.txt");
// 尝试从文件中读取一行
std::string line;
std::getline(file, line);
// 检查流的状态
std::cout << std::boolalpha; // 设置为输出bool值为true/false而非1/0
// 检查是否到达文件末尾(EOF)
std::cout << "EOF detected: " << (file.eof() ? "true" : "false") << std::endl;
// 注意:如果文件不存在,eof()可能不会被置位,直到尝试读取并失败
// 检查是否发生I/O操作失败
std::cout << "Failbit set: " << (file.fail() ? "true" : "false") << std::endl;
// 当文件不存在或无法读取时,failbit通常会被置位
// 检查流是否崩溃(如磁盘错误)
std::cout << "Badbit set: " << (file.bad() ? "true" : "false") << std::endl;
// 在这个例子中,badbit通常不会被置位,除非发生严重的I/O错误
// 检查流是否处于良好状态
std::cout << "Goodbit set: " << (file.good() ? "true" : "false") << std::endl;
// 如果failbit、badbit或eofbit中的任何一个被置位,good()将返回false
// 检查流的当前状态(返回一个包含所有置位标志的iostate值)
std::iostate state = file.rdstate();
std::cout << "Current state: " << state << std::endl; // 这里可能会输出一些数字,代表状态位的组合
// 重置流的状态
file.clear(); // 清除所有状态标志
// 再次检查流是否处于良好状态
std::cout << "After clear, Goodbit set: " << (file.good() ? "true" : "false") << std::endl;
// 使用特定的标志位重置流状态(这里是一个示例,实际上通常不需要这样做)
file.clear(std::ios::failbit); //重置failbit
return 0;
}
4、管理输出缓冲
每个输出流都管理一个缓冲区,用来保存程序读写的数据。
导致缓冲区刷新的原因(数据真正写道输出设备或者文件)的原因有:
-
程序结束,main函数中的return语句。
-
缓冲区满了。
-
使用操作符(如endl、flush、ends)显示刷新。
cout << "hi!" << endl; //输出hi和换行,然后刷新 cout << "hi!" << flush; //输出hi,然后刷新 cout << "hi!" << ends; //输出hi和一个空字符,然后刷新
-
在每个输出操作符之后,我们可以用unitbuf设置流的内部状态,来清空缓冲区。
在C++中,std::ios_base::unitbuf 是一个控制标志,用于控制流缓冲区的行为。当设置了 unitbuf 标志时,流会在每次插入操作(如 << 输出操作符)后立即刷新其缓冲区,这意味着输出将不会被缓存,而是直接写入到其关联的设备(如文件、控制台等)中。
std::ofstream file("file.txt"); // 设置unitbuf标志,使每次输出后都刷新缓冲区 file.setf(std::ios::unitbuf); // 写入一些文本到文件,每次写入后都会刷新缓冲区 file << "Hello, " << "world!" << std::endl; // 你可以通过unsetf取消unitbuf的设置 // file.unsetf(std::ios::unitbuf);
简单方式
cout << unitbuf; //所有输出都会刷新缓冲区 cout << nounitbuf; //返回正常缓冲方式
-
一个流可能被关联到另一个流。这是当读写被关联流时,关联到流的缓冲区会被刷新。
例如:cin和cerr都被关联到cout。因此,读cin或者写cerr都会导致cout缓冲区刷新。
二、文件输入输出
fstream中独特的操作。
操作 | 描述 |
---|---|
fstream fstrm; |
创建一个未绑定的文件流。fstream 是头文件 fstream 中定义的一个类型。 |
fstream fstrm(s); |
创建一个 fstream 对象,并打开名为 s 的文件。默认的文件模式(mode )依赖于 fstream 的类型。 |
fstream fstrm(s, mode); |
与前一个构造函数类似,但按指定的 mode 打开文件。mode 可以是如 std::ios::in 、std::ios::out 、std::ios::app 、std::ios::binary 等的组合。 |
fstrm.open(s); |
打开名为 s 的文件,并将文件与 fstrm 绑定。默认的文件模式(mode )依赖于 fstream 的类型。 |
fstrm.open(s, mode); |
打开名为 s 的文件,并将文件与 fstrm 绑定,同时指定打开模式 mode 。 |
fstrm.close(); |
关闭与 fstrm 绑定的文件。返回 void 。 |
fstrm.is_open(); |
返回一个 bool 值,指出与 fstrm 关联的文件是否成功打开且尚未关闭。 |