IO库

1 C++缓冲区

在学习标准IO库之前,我们先了解C++中缓冲区的使用。关于操作系统中缓冲区的学习与理解,请查看操作系统-缓存管理

1.1 什么是缓冲区

缓冲区又称缓存,是内存空间的一部分。系统在内存中预留一部分用于缓冲输入输出的数据,缓冲区根据用途分为输入缓冲区输出缓冲区两种。

1.2 为什么要引入缓冲区

C++中缓冲区的使用主要有以下几个目的:

  • 缓和CPU与I/O设备间速度不匹配的矛盾。
  • 减少对CPU的中断频率,放宽对CPU中断响应时间的限制。
  • 提高CPU和I/O设备之间的并行性,让CPU可以处理其他工作
1.3 缓冲区类型

C++缓冲区分为全缓冲、行缓冲和无缓冲三种。

  • 全缓冲
    在此类缓冲中,当填满标准I/O缓冲后,才进行实际的I/O操作。典型的代表是磁盘文件的读写。

  • 行缓冲
    在此类缓冲中,当在输入和输出中遇到换行符时,执行真正的I/O操作。输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。

  • 无缓冲
    标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

1.4 缓冲区的刷新

下列情况将导致缓冲区刷新

  • 程序正常结束
    作为main函数return的一部分,缓冲刷新被执行。

  • 缓冲区满
    需要刷新缓冲,新数据才可写入。

  • 使用操作符控制缓冲区刷新
    endl:输出内容加换行,然后刷新
    ends:输出内容加空字符,然后刷新
    flush:输出内容后直接刷新

  • unitbuf设置流的内部状态

cout << unitbuf; //所有输出操作后会立即刷新缓冲区
cout << <<nounitbuf; //回到正常的缓冲方式
  • 一个输出流被关联到另一个流上
    使用tie函数可以将两个流关联在一起。当读写被关联的流,被关联的流会刷新。cincerr都关联到cout,因此读cin或者cerr都会导致cout的缓冲区更新。我们可以将istream关联到ostream上,也可将ostream关联到另一个ostream上。不建议将cin关联到cerr上。

警告:如果程序崩溃了,则不会刷新缓冲区。

1.5 行缓冲演示

getchar()是行缓冲的,第一次调用getchar()函数,会让程序使用者输入一行字符并直至按下回车键函数才返回。此时用户输入的字符和回车符都存放在行缓冲区。再次调用getchar()函数,会逐步输出行缓冲区的内容。

int main(){
    char c;
    c = getchar();
    cout << c << endl;
    while ((c = getchar())!= '\n'){
        cout << c << endl;
    }
}
/*一次性输入 a b c
输出
a
b
c
*/

2 IO类

iostream中的类型和对象都是操作char数据的。默认情况下,这些对象都是关联到用户控制台的窗口的。

为了支持不同种类的IO处理操作,在istreamostream之外,标准库还定义了一些其他的IO类型。iostream定义了用于读写流的基本类型,fstream定义了读写命名文件的类型,sstream定义了读写内存string对象的类型。

为了支持宽字符的语言,标准库定义了一组类型和对象来操作wchar_t类型的数据。宽字符版本的类型和函数的名字以一个w开始,与其普通char版本定义在同一个头文件中。

2.1 IO对象无拷贝

由于不能拷贝IO对象,因此我们不能将形参或返回类型设置为流类型。进行IO的函数通常以引用方式传递和返回流。读写一个IO对象会改变其状态,因此传递和返回的引用不能是const

2.2 条件状态

IO类所定义的一些函数和与机器无关的iostate标志,可以帮助我们访问和操作流的条件状态

1) 条件状态说明

上述任何一个IO对象在任意时刻都有一种状态,iostate代表状态的枚举,badbit,failbit,eofbit,goodbitiostate的一个具体值。

操作good在所有错误位均未置位的情况下返回true。而badbitfailbiteofbit任一被置位,检测流的状态条件会失败,此时fail操作返回truebadfaileof只有在相应错误为被置位时才返回true

一个流一旦发生错误,其上后续的IO操作都会失败。只有当一个流处于无错状态时,我们才可对它读写数据。通常用以下语句检查一个流在使用前的状态:

while (cin >> word)
    //输入操作成功,流保持有效,条件状态为真

** 2) 条件状态管理**

流对象的rdstate成员返回一个iostate值,对应流的当前状态。setstate操作将给定条件为置位,表示发生了对应错误。

clear成员是一个重载函数,提供两个版本:clear无参数版本将复位所有错误标志位,带参数版本提供一个新的iostate状态。

2.3 管理输出缓冲

关于缓冲区内容本章开头有介绍。

3 文件输入输出

ifstream从一个给定的文件读取数据,ofstream向一个给定文件写入数据,fstream可以读写给定文件。

可以用getline函数从一个ifstream读取数据,除继承自iostream类型中行为外,fsteam还提供了一下成员来管理与流关联的文件。

3.1 使用文件流

当需要读写一个文件时,可以定义一个文件流对象,并将对象与文件关联起来。文件名可以用string类型,也可以用传统C风格字符串。

1) 成员函数open和close

如果我们定义了一个空文件流对象,可以随后用open将它与文件关联起来。如果调用open失败。failbit将会被置位。因此检测open是否成功是一个好习惯。

使用close函数可关闭文件流所绑定的文件。

string text;
ifstream fstm;
fstm.open("test.txt");
if (fstm){
    getline(fstm, text);
    cout << text;
    fstm.close();
}
else{
    cout << "failed";
}
\\如果顺利打开test.txt,条件为真,则从中读取内容,输出并关闭文件
\\打开失败则输出failed

2) 自动构造和析构

当一个fstream离开其作用域,close会自动被调用,与之关联的文件会自动关闭。

3.2 文件模式

在打开文件时,无论是调用 open还是以文件名作为流初始化的一部分,都需指定文件模式(file mode)。

  • 只可以对ofstreamfstream对象设定out模式

  • 只可以对ifstreamfstream对象设定in模式

  • 只有打开out模式,才可设定trunc模式

  • 只要trunc模式未被设定,就可设定app模式。在app模式下,即使没有显示指定out模式,文件也总以输出模式被打开

  • 默认情况下,以out模式打开文件,在位指定trunc时,也将被截断。为保留其中内容,可以使用app模式或者in模式(文件同时读写)

  • atebinary模式可用于任何类型的文件流对象且可以与其他模式组合使用。ate 模式只在打开时有效:文件打开后将定位在文件尾。以 binary模式打开的流则将文件以字节序列的形式处理,而不解释流中的字符。

默认情况下,当我们打开一个ofstream时,文件内容会被丢弃。对于用 ofstream 打开的文件,要保存文件中存在的数据,唯二方法是显式地指定app模式或 in 模式打开:

4 string流

sstream头文件中定义了以下三个类型来支持内存IO。

istringstreamstring中读取数据,ostringstreamstring中写入数据,而stringstream即可从string读数据也可以向string写数据。出了从iostream中继承的操作外,sstream中还支持以下操作:

4.1 sstream的使用
string line, word; 
while (getline(cin, line)) {
    istringstream stream(line);
    while (stream >> word){
        // do per-word processing
    }
}

string中数据全部读出后,同样会触发“文件结束”信号,此时while循环条件为false

4.2 转换或格式化

sstream类似于C语言风格中ssprintf,可以方便地构造各种风格的string

string format_message = "cp 3 lbj 23";
istringstream input(format_message);
ostringstream output;

int val1 = 0, val2 = 0;
string str1, str2;

input >> str1 >> val1 >> str2 >> val2;
output << val1 << " " << val2 << endl; 
cout << output.str();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 版权声明:本文为 cdeveloper 原创文章,可以随意转载,但必须在明确位置注明出处! 标准 IO 库 上一篇...
    登龙zZ阅读 653评论 0 3
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,845评论 18 139
  • I/O 库提供了两套不同风格的文件处理接口。 第一种风格使用隐式的文件句柄; 它提供设置默认输入文件及默认输出文件...
    chiguozi阅读 6,659评论 1 4
  • 开发工作中我们都需要选择一个文本编辑器,从最开始的EditPlus 到nodepad++,还有UltraEdit ...
    一笑yo阅读 266评论 0 2
  • 如果上市公司董秘技能水平都不及保荐代表人,或者独立第三方服务机构(律所、会计师事务所,评估机构等),那么上市公司的...
    桃子torri阅读 1,024评论 2 6