8.1 IO类
之前章节用过的IO库设施:
- istream:输入流类型,提供 输入操作。
- ostream:输出流类型,提供 输出操作。
- cin:一个istream对象,从标准输入 读取数据。
- cout:一个ostream对象,向标准输出 写入数据。
- cerr:一个ostream对象,向标准错误 写入消息。
- >>运算符:从一个istream对象中 读取输入数据。
- <<运算符:向一个ostream对象中 写入输出数据。
- getline函数:从一个给定的istream对象中 读取一行数据,存入到一个给定的 string对象中。
(1) IO库类型和头文件:
IO库类型和头文件 | |
头文件 | 类型 |
iostream | istream,wistream从流读取数据 |
ostream,wostream 向流写入数据 | |
iostream,wiostream 读写流 | |
fstream | ifstream,wifstream 从文件读取数据 |
ofstream,wofstream 向文件写入数据 | |
fstream,wfstream 读写文件 | |
sstream | istringstream,wistringstream 从string读取数据 |
ostringstream,wostringstream 向string写入数据 | |
stringstream,wstringstream 读写string |
(2) IO对象无拷贝或赋值:
- IO对象不能存在容器里。
- 形参和返回类型也不能是流类型,一般是流的引用。
- 读写一个IO对象会改变其状态,因此传递和返回的引用 不能是const的。
(3) 条件状态:
I0库条件状态 | |
strm: : iostate | strm是一种IO类型。iostate是一种机器相关的类型,提供了表达条件状态的完整功能 |
strm: :badbit | 用来指出 流已崩溃 |
strm: : failbit | 用来指出 一个IO操作失败了 |
strm: :eofbit | 用来指出 流到达了文件结束 |
strm: :goodbit | 用来指出 流未处于错误状态。此值保证为零 |
s.eof () | 若流s的 eofbit置位,则返回true(s是一个流对象) |
s.fail () | 若流s的 failbit或badbit置位,则返回true |
s.bad () | 若流s的 badbit置位,则返回true |
s.good () | 若流s处于 有效状态,则返回true |
s.clear () | 将流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 |
注:一个流一旦发生错误,其上后续的 IO操作都会失败。只有当一个流处于 无错状态时,我们才可以对其操作。(由于流可能处于错误状态,因此代码通常应该 在使用一个流之前 检查它是否处于良好状态)
// 确定一个流对象的状态的最简单的方法 是将它当作一个条件来使用: while(cin>>wort){ // 等价于while(!cin.fail()) // ok }
(4) 管理输出缓冲:
每个输出流 都管理一个缓冲区,执行输出的代码,文本串可能立即打印出来,也可能被操作系统保存在缓冲区内,随后再打印。
关于刷新缓冲区,可以使用如下IO操纵符:
(2) 文件模式:
- endl:输出一个换行符 并刷新缓冲区。
- flush:刷新流,但不添加任何字符。
- ends:在缓冲区插入空字符null,然后刷新缓冲区。
- unitbuf:告诉流接下来每次操作之后 都要进行一次flush操作。
- nounitbuf:重置流,使其恢复使用 正常的系统管理的 缓冲区刷新机制。
(5) 关联输入和输出流:当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。
std::cin.tie(&cout); // 将cin和cout关联在一起(标准库默认将cin和cout关联在一起) int a; std::cin >> a; // 该语句将导致cout的缓冲区被刷新
- tie() 的重载版本1:不带参数,返回指向输出流的指针。(如果本对象当前 关联到一个输出流,则返回的就是 指向这个流的指针,如果对象未关联到流,则返回空指针)
- tie() 的重载版本2:接受一个指向 ostream的指针,将自己关联到此ostream。
注:每个流同时 最多关联到一个流,但多个流可以同时 关联到同一个ostream。
8.2 文件输入输出
头文件fstream 定义了三个类型来支持文件IO:- ifstream:从一个给定文件读取数据。
- ofstream:向一个给定文件写入数据。
- fstream:可以读写给定文件。
(1) fstream特有的操作:
操作 | 解释 |
fstream fstrm; | 创建一个未绑定的文件流。(fstream是头文件fstream中 定义的一个类型;fstrm是一个文件流对象) |
fstream fstrm(s); | 创建一个文件流,并打开名为s的文件,s可以是string 也可以是C分格字符串指针。 |
fstream fstrm(s, mode); | 与前一个构造函数类似,但按指定mode打开文件。 |
fstrm.open(s) | 打开名为s的文件,并和fstrm绑定。 |
fstrm.close() | 关闭和fstrm绑定的文件,返回void。 |
fstrm.is_open() | 返回一个bool值,指出与fstrm关联的文件 是否成功打开且尚未关闭。 |
每个流都有一个 关联的文件模式,用来指出如何使用文件。
文件模式 | 解释 |
in | 以读的方式打开 |
out | 以写的方式打开 |
app | 每次写操作前 均定位到文件末尾 |
ate | 打开文件后 立即定位到文件末尾 |
trunc | 截断文件 |
binary | 以二进制方式进行IO操作 |
- 只可以对ofstream或fstream对象 设定out模式。
- 只可以对ifstream或fstream对象 设定in模式。
- 只有当 out也被设定时 才可设定trunc模式。
- 只要trunc没被设定,就可以设定app模式。在app模式下,即使没有显式指定out模式,文件也总是以 输出方式被打开。
- 默认情况下,即使我们没有指定trunc,以out模式打开的文件 也会被截断。为了保留以out模式打开的 文件的内容,我们必须同时指定app模式,这样只会将数据 追加写到文件末尾;或者同时指定in模式,即打开文件同时进行读写操作。
- ate和binary模式可用于 任何类型的文件流对象,且可以与其他任何文件模式 组合使用。
注:
- 每个文件流类型都定义了 一个默认的文件模式。当我们未指定文件模式时,就使用此默认模式。
- 对于一个给定流,每当打开文件时,都可以改变其文件模式。
int main() { std::ofstream out; // 未指定文件打开模式 out.open("aaa.txt"); // 模式隐含设置为 输出(out)和截断(trunc) (文件以隐含out模式打开。通常情况下,out模式意味着同时使用trunc模式。因此,当前目录下名为aaa.txt的文件的内容将被清空。) out << "aaa"; // "aaa.txt"文件内容为aaa out.close(); // 关闭out out.open("aaa.txt"); out << "bbb"; // "aaa.txt"文件内容为bbb,之前的内容aaa 在写入之前将被清空了 out.close(); out.open("aaa.txt", std::ofstream::app); // 模式设置为 输出(out)和追加(app) out << "ccc"; // "aaa.txt"文件内容为bbbccc,之前的内容bbb 被保留下来了 out.close(); }
8.3 string流
头文件sstream 定义了三个类型来支持内存IO:
- istringstream:从string读取数据。
- ostringstream:向string写入数据。
- stringstream:可以读写给定string。
操作 | 解释 |
sstream strm; | 定义一个未绑定的stringstream对象(sstream 是头文件sstream中定义的一个类型) |
sstream strm(s); | 用string s初始化对象strm |
strm.str(); | 返回strm所保存的 string的拷贝 |
strm.str(s); | 将string s拷贝到strm中。返回void |
int main() { int a = 100; string str = "aaa"; string result; std::istringstream istr(str); // 将 istringstream对象istr 绑定到 string对象str std::ostringstream ostr; std::stringstream iostr; istr >> result; // 从istr中读取数据到result cout << result << endl; // 输出 "aaa" ostr << a; // 将a写入ostr; cout << ostr.str() << endl; // 输出 100 iostr << a; // 将a写入iostr; iostr >> result; // 从iostr中读取数据到result cout << result << endl; // 输出 "100" }