C++IO流简介

1.输入输出(IO)与流的概念

输入输出(IO)是指计算机同任何外部设备之间的数据传递。常见的输入输出设备有文件、键盘、打印机、屏幕等。数据可以按记录(或称数据块)的方式传递,也可以 流的方式传递。

所谓记录,是指有着内部结构的数据块。记录内部除了有需要处理的实际数据之外,还可能包含附加信息,这些附加信息通常是对本记录数据的描述。

流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出。

C++IO流,特指以流的方式进行输入输出的ISO/ANSI标准C++库的输入输出类库,也就是专门负责处理IO操作的一套系统。任何需要传递的数据,都要经过这套系统的处理。

2.数据的表示形式

IO操作的过程中,任何需要被传递的数据,在经过IO类库处理前后是不同的。这样,我们可以把数据的表示分为两种:内部表示和外部表示。

数据的内部表示便于程序进行数据处理。典型的内部表示有:整型数的二进制表示、浮点数的IEEE表示、字符的ASCII或Unicode编码表示。数据的外部表示则根据不同的外部设备的需要,有具体不同的表现形式。如果外部数据表示是可读的字符序列,则称为文本IO,否则为二进制IO。标准IO流的主要目的是支持文本IO,不直接支持二进制IO。

虽然IO流是以流的方式进行数据传递,但这并不表明传递的数据不能有任何结构,而是指IO流的概念是以流的方式进行输入输出,所传递数据的内部结构隐藏在对流数据的解释中。

3.IO的步骤

在IO流里,输入输出分为4步:格式化/解析,缓冲,编码转换和传递。

格式化/解析:在内部数据表示(以字节为单位)与外部数据表示(以字符为单位)之间进行双向转换。例如一个2字节的整数10002,就需要5个字符来表示。

缓冲:用于在格式/解析与传递只加缓存字符序列。对于输出,较短的字符序列格式化之后并不马上输出,而是保存在缓冲区里,待累积到一定规模之后再传递到外部设备。相反,从外部设备读入的大量数据也是先放在缓冲区,然后逐步取出完成输入。默认时,IO流的输入输出都是经过缓冲的,也可以让IO流工作在无缓冲模式下。

编码转换: 是将一种字符表达式转换成另一种字符表达式。如果格式化产生的字符表达式与外部字符表达式不同(输出时),或者外部表达式与IO流能解析的表达式不同(输入时),就必须进行编码转换。如多字节编码与宽字符编码之间的转换等。多数情况下并不需要进行编码转换。

传递:主要是与外部设备进行通信。输出时,传递负责将经过格式化、缓冲即编码转换后的字符序列发送到外部设备;输入时,则负责将外部设备抽取数据,为其后进行的编码转换、缓冲及解析提供字符序列。

4.IO流类库的组成结构

IO流类库在不同平台的具体实现上,可能会有所变化,但从总体设计上来看,C++流库主要由两个流类层次组成:

(1)以streambuf类为父类的类层次 主要完成信息通过缓冲区的交换。派生层次如下:

缓冲区:是一个队列数据结构,由一字符序列和两个指针组成,这两个指针分别指向字符要被插入或被取出的位置。 streambuf类为所有的streambuf类层次对象设置了一个固定的内存缓冲区,动态划分为两部分: 用做输入的取区,用取指针指示当前取字符位置。 用做输出的存区,用存指针指示当前存字符位置。

(2)以ios类为父类的类层次 ios类及其派生类是在streambuf类实现的通过缓冲区的信息交换的基础上,进一步增加了各种格式化的输入/输出控制方法。它们为用户提供使用流类的接口,它们均有一个指向streambuf的指针。

ios类有四个直接派生类: istream ostream fstreambase strstreambase

这四种流作为流库中的基本流类。ios类的派生层次如下:

5. IO流类库的优点

C++语言开发了自己的IO流类库,用以取代C语言的基本输入输出函数族。对于有经验的C程序员来说,C语言提供的IO函数库时有效且方便的。但是,C语言的IO函数库有其自身的缺点,特别是在C++这种面向对象的程序设计语言中,C语言函数库无法直接支持面向对象的程序设计。因此,C++语言开发自己的IO流类库是必然的。具体来说,IO流类库具有以下优点。

(1)简明与可读性 IO流类库用IO运算符(提取运算符>>和插入运算符<<)代替了不同的输入输出函数名,如printf和scanf等。从直观来看,这种改变使得IO语句更为简明。另外,也减轻了程序员在记忆函数名和书写程序上的一些负担。例如:

printf(“n=%d,a=%f\n”,n,a);
cout<<”n=”<<n<<”,a=”<<a<<endl;

虽然两条语句的输出结果是一样的,但是后者更加简明,直观,易写,易读。

(2)类型安全(type safe) 所谓类型安全,是指编译器所理解的数据实体(如变量。指针所指向的数据等)的类型,与实际数据实体的实际类型或对该数据所进行的操作之间保持一致性。在进行IO操作时,编译器将自动检查实参的表达式类型来调用IO流类相应的重载版本的成员函数,来完成输入输出。而采用C的IO函数,必须显示指明操作的数据类型,如采用printf()函数,由于其参数中的数据类型必须由程序员以参数格式%d,%f,%c,%s,容易出错。

(3)易于扩充 C++语言的IO流类库,是建立在类的继承关系、模板和操作符重载等机制的基础上的。把原来C语言中的左、右移位运算符<<和>>,通过运算符重载的方法,定 义为插入(输出)和提取(输入)运算符。这就为输入输出功能对于各种用户定义的类型数据的扩充,创造了方便的条件。

用户可以采用输入输出操作符的重载来完成用户想要的输入输出功能。例如,用于复数类Complex的输出操作符重载函数可以定义为:

friend ostream& operator<<(ostream& s,const Complex& c){
    s<<c.real<<"+"<<c.image<<"i"<<endl;
    return s;
}

输入输出操作符有个固定的格式,以上是一种常用的格式。由于C语言并不支持函数重载,也不直接支持面向对象的程序设计,所以想扩充C语言的输入输出函数使它们支持用户定义的新数据类型,是一件非常困难的事情。


参考文献

[1]陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008[P323-P326]. [2]http://wenku.baidu.com/view/61ed0dc2d5bbfd0a79567328.html?re=view

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • getopt()、getopt_long()与getopt_long_only()获取命令行参数

    众所周知,C/C++程序的主函数有两个参数。第一个参数是整型,可以获得包括程序名字的参数个数,第二个参数是字符数组指针或字符指针的指针,可以按顺序获得命令行上各...

    Dabelv
  • C++多态的两种形式

    多态(Polymorphisn)是面向对象程序设计(OOP)的一个重要特征。多态字面意思为多种状态。在面向对象语言中,一个接口,多种实现即为多态。C++中的多态...

    Dabelv
  • 2018腾讯内部调岗面试试题1——使用C/C++但不能用sizeof判断操作系统是32位还是64位

    2018上半年折腾了一回,想换个后台开发岗尝试锻炼一下自己,面了三个部门,将有关有意思的题目汇总记录下来,供大家参考。

    Dabelv
  • 理解Linux里面的IO模型

    User space(用户空间)和 Kernel space(内核空间)。Linux里面这么设计的目的主要是为了安全,即使用户空间崩溃了,内核也不受影响。所以在...

    我是攻城师
  • IO FILE之劫持vtable及FSOP

    之前的文章对IO FILE相关功能函数的源码进行了分析,后续将对IO FILE相关的利用进行阐述。

    迅达集团
  • 第02问:怎么模仿磁盘 IO 慢的情况?

    将块设备 /dev/loop3 映射成带延迟的设备(对于读操作和写操作都延迟 100ms)

    爱可生开源社区
  • Gartner 2016-2020技术趋势预测分析报告

    多年以来,Gartner的研究数据与咨询服务被认为是客观技术思想领导的权威来源。作为全球IT市场预测与咨询的龙头,Gartner每年对外输出数十份市场研究报告,...

    腾讯安全
  • Web APP编程模型和IO策略

    现代大型高性能网站诸如淘宝,京东,微博,FB,知乎等等,网站架构涉及很多知识。像业务分层,软件分割模块化,分布式部署,集群服务器,负载均衡等技术可以帮助架构师将...

    小小科
  • 2015年科技圈最挣钱的14个行业 可视化大数据时代

    终于走到了2014年的尾声,各位科技圈的热心网友们,对新的一年又有些什么期待呢?不妨设想下,明年会发生哪些“XX技术”奇迹。国外科技媒体BusinessInsi...

    小莹莹
  • 四、node服务器搭建

    静态服务器实现与读取网页返回几乎一致,通过request.url可以获取用户访问的路径。

    Dreamy.TZK

扫码关注云+社区

领取腾讯云代金券