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();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

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