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
注:为了支持使用 宽字符的语言,标准库定义了一组类型和对象 来操纵wchar_ t类型的数据。宽字符版本的类型和函数的名字 以一个w开始。

(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操纵符:
  • 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关联的文件 是否成功打开且尚未关闭。

(2) 文件模式:
每个流都有一个 关联的文件模式,用来指出如何使用文件。
文件模式 解释
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。

(1) stringstream特有的操作:
操作
解释
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"
}