- 什么标准IO?为了说明这个概念,这里我们讲述一个例子。
门卫老大爷负责把公司里的信件送到到邮局,
下面有两种送法:
1他去一次邮局要花费 10 分钟的时间,而每次最多能送 20 封信,每当信件累计到 20 封的时候他就要动身去邮局了。
2但是当他收到一封加急的邮件时,就会立即去一趟邮局。
系统 IO 就好比每收到一封信时都要去一趟邮局,所以实时性高。而标准 IO 就好比要攒够 20 封信才去一趟邮局,所以吞吐量高,因为用户把信件交到老大爷的手上时就会立即返回,响应速度快,用户体验更好。而我们使用 fflush(3) 之类的函数强制刷新缓冲的时候,就相当于是老大爷收到了一封加急信件需要立即去一趟邮局送信。
标准io与系统io的比较
类型 | 可移植性 | 实时性 | 吞吐量 | 功能 |
STDIO | 高 | 低 | 高 | 受限 |
SYSIO | 低 | 高 | 低 | 自由 |
表格中的每一项都是两者之间相对而言,使用哪种 IO 并没有绝对的好坏之分,要根据实际的需求来决定应该使用哪个。
可移植性:
标准 IO 是 C89 支持的函数,所以使用了标准 IO 的程序无论在 Linux 平台还是换成了 Windows 平台,不用修改代码是可以直接编译运行的。
而系统 IO 是由内核直接提供的函数库实现的,不同的操作系统平台上提供的 IO 操作接口是不同的,所以想要移植使用了系统 IO 的程序,必须按照目标平台的 IO 库修改程序并重新调试。
所以你写的程序将来可能在不同的平台上运行,那么最好使用标准 IO 库;如果你的程序是专门针对于某个平台而开发的,那么使用系统 IO 库能够得到我们下面说的其它优势。
- 涉及的知识
流和FILE
缓冲:
标准io提供缓存的目的是尽可能减少使用read和write调用的数量。它也对每个io流自动地今次那个缓存管理,避免了应用程序需要考虑这一点带来的麻烦。它提供三种类型的缓存
- 全缓存。这种情况下,当填满标准io缓存后才进行实际io操作。对于驻在磁盘上的文件通常是由标准io库实施全缓存。在一个流上执行第一次io操作时,相关标准io函数通常调用malloc获取使用的缓存。缓存可由标准io例程自动执行刷新(例如当填满一个缓存)或者可以调用fflush()刷新一个流。
- 行缓存。这种情况下,当输入和输出中遇到新行标准(或者缓存区写满)io库执行io操作。这允许我们一次输出一个字符,但只有在写了一行后才进行实际的io操作。当流设计一个终端时,典型地使用行缓存。
- 不带缓存。标准io库不对字符进行缓存。如果用标准io函数写若干字符到不带缓存的流中,则相当于用write系统调用函数将这一般来说,标准出错是不带缓冲区的,打开终端设备流(如:stdin,stdout)为行缓冲,其他时候为全缓冲;这里涉及到了3个函数:更改缓冲类型:打开和关闭缓冲机制:void setbuf(FILE *steam, char *buf);更改流的缓冲模式:int setvbuf(FILE *stream, char *buf, int type, unsigned size);刷新缓冲区:强制刷新一个流:int fflush(FLIE*stream);
EOF的什么? ----------> 详见另一篇博文
- 标准IO涉及的常用操作
打开:打开一个流
返回值:文件顺利打开后,向该流的就会被返回。如果文件打开失败则返回NULL,并把存在中。一般而言,打开文件后会做一些文件读取或写入的动作,若打开文件失败,接下来的读写动作也无法顺利进行,所以一般在fopen()后作错误判断及处理。
- 注意:字段“b” 和其组合有些C可能不完全提供所有这些功能 。并且有的C版本不用"r+","w+","a+",而用"rw","wr","ar"等,读者注意所用系统的规定。
- 1.在系统中,文本模式下,文件以"\r\n"代表换行。若以文本模式打开文件,并用fputs等函数写入换行符"\n"时,函数会自动在"\n"前面加上"\r"。即实际写入文件的是"\r\n"
- 2.在类Unix/Linux系统中文本模式下,文件以"\n"代表换行。所以Linux系统中在文本模式和二进制模式下并无区别。
关闭:关闭一个流
。注意:使用fclose()函数就可以把内最后剩余的数据输出到内核缓冲区,并释放和有关的缓冲区。
两个常用错误输出函数:
perror:将上一个函数发生错误的原因直接输出到 stdout
函数原型 :void
perror
(
const
char
* str );
参数:str :参数str所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。
注意:perror输出错误的时效
strerror: 将单纯的错误标号转为字符串描述
函数原型 :char
*
strerror
(
int
errnum);
参数:errnum:错误标号,通常用errno(标准错误号,定义在errno.h中)
返回值:指向错误信息的(即:错误的描述字符串)
- 标准IO中遇到的问题