读书笔记-APUE第三版-(5)标准IO库
2014-05-04 21:24
295 查看
ISO C标准I/O库使用流的概念读写文件。流是对数据传输的抽象,可以把流理解为从起点到终点间的字节序列。
标准I/O库通过维护进程空间内的缓冲区,减少read/write系统调用次数来提高I/O效率。之前介绍的Unbuffered I/O和文件描述符fd打交道,标准I/O则使用FILE指针。
Fully buffered(全缓冲):通常情况下,硬盘上的文件读写操作都使用全缓冲,当缓冲区满的时候才触发flush操作。
Line buffered(行缓冲):行缓冲一般用于终端下的标准输入/输出操作,遇到换行符或者缓冲区满时都会发生I/O操作。(注:当标准I/O库不使用缓冲或者使用行缓冲需要从内核读取数据时,行输出缓冲会被flush)。
Unbuffered(不缓冲):标准错误输出不使用缓冲。
三个预定义的文件流指针被自动打开,分别是stdin标准输入、stdout标准输出和stderr标准错误流。
关闭文件:int fclose(FILE *fp);所有缓冲输出数据被flush,缓冲输入数据被丢弃。进程正常退出时,所有文件流被自动关闭
读取函数包括getc(通常为宏)/fgetc(不能是宏,只能是函数)/getchar(从标准输入流读取),它们都返回int整数,从unsignedchar转换而来,这样正常返回值都是正数,可以和EOF(典型值为-1)区分出来。
使用fgets/gets/fputs/puts要注意以下问题:缓冲区溢出,是否自动添加\0和\n等。
标准I/O的User CPU时间较高,因为相比第一行read/write操作BufferSize使用4096 ,标准I/O的while循环次数要多得多。
标准I/O的System CPU时间接近最优化状态,可见标准I/O会使用合适的缓冲区大小。
最后一行每读写一个字节都进行系统调用,所以性能最差
格式化:printf家族:printf(标准输出)/fprintf(输出到文件)/sprintf(输出到字符数组缓冲区)/snprintf(指定缓冲区大小避免溢出)。相对应的是scanf家族。
临时文件:tmpnam(返回唯一路径)/tmpfile(创建临时文件,关闭后被自动删除)/mkdtemp/mkstemp(能指定临时文件名模板)。
内存流:fmemopen,把某段内存当做FILE流返回,然后进行I/O操作,一般用于创建字符串
标准I/O库通过维护进程空间内的缓冲区,减少read/write系统调用次数来提高I/O效率。之前介绍的Unbuffered I/O和文件描述符fd打交道,标准I/O则使用FILE指针。
typedef struct{ short level;/*缓冲区满程度*/ unsigned flags;/*文件打开状态标志*/ char fd;/*文件描述符*/ unsigned char hold;/*若无缓冲区不读取*/ short bsize; /*缓冲区大小*/ unsigned char *buffer; /*缓冲区位置*/ unsigned ar *curp; /*当前读写位置*/ unsigned istemp; /*临时文件指示*/ short token; /*用作无效检测*/ }FILE;
缓冲区
在打开文件时,标准I/O库负责自动分配缓冲区,还可以通过setbuf/setvbuf函数显式设置缓冲区类型、大小甚至关闭缓冲区。Fully buffered(全缓冲):通常情况下,硬盘上的文件读写操作都使用全缓冲,当缓冲区满的时候才触发flush操作。
Line buffered(行缓冲):行缓冲一般用于终端下的标准输入/输出操作,遇到换行符或者缓冲区满时都会发生I/O操作。(注:当标准I/O库不使用缓冲或者使用行缓冲需要从内核读取数据时,行输出缓冲会被flush)。
Unbuffered(不缓冲):标准错误输出不使用缓冲。
打开/关闭文件
打开文件:FILE *fopen(const char *restrict pathname, const char *restricttype);打开类型如下:三个预定义的文件流指针被自动打开,分别是stdin标准输入、stdout标准输出和stderr标准错误流。
关闭文件:int fclose(FILE *fp);所有缓冲输出数据被flush,缓冲输入数据被丢弃。进程正常退出时,所有文件流被自动关闭
读写操作
字符读写
#include"apue.h" int main(void) { int c; while ((c = getc(stdin)) != EOF) if (putc(c, stdout) == EOF) err_sys("output error"); if (ferror(stdin)) err_sys("input error"); exit(0); }
读取函数包括getc(通常为宏)/fgetc(不能是宏,只能是函数)/getchar(从标准输入流读取),它们都返回int整数,从unsignedchar转换而来,这样正常返回值都是正数,可以和EOF(典型值为-1)区分出来。
行读写
#include"apue.h" int main(void) { char buf[MAXLINE]; while (fgets(buf, MAXLINE, stdin) != NULL) if (fputs(buf, stdout) == EOF) err_sys("output error"); if (ferror(stdin)) err_sys("input error"); exit(0); }
使用fgets/gets/fputs/puts要注意以下问题:缓冲区溢出,是否自动添加\0和\n等。
二进制读写
fread和fwrite函数用于读写二进制数据。要注意的是,由于字节对齐、字节顺序、编译器、计算机体系结构差异,二进制读写兼容性比较差。struct { short count; long total; char name[NAMESIZE]; } item; if(fwrite(&item, sizeof(item), 1, fp) != 1) err_sys("fwrite error");
效率对比
标准I/O的User CPU时间较高,因为相比第一行read/write操作BufferSize使用4096 ,标准I/O的while循环次数要多得多。
标准I/O的System CPU时间接近最优化状态,可见标准I/O会使用合适的缓冲区大小。
最后一行每读写一个字节都进行系统调用,所以性能最差
其他重要函数
文件流定位:ftell(返回long)/ftello(返回off_t)/fseek/fseeko/rewind/fgetpos/fsetpos,后两个是ISO C标准中定义的,可以在非UNIX系统中使用格式化:printf家族:printf(标准输出)/fprintf(输出到文件)/sprintf(输出到字符数组缓冲区)/snprintf(指定缓冲区大小避免溢出)。相对应的是scanf家族。
临时文件:tmpnam(返回唯一路径)/tmpfile(创建临时文件,关闭后被自动删除)/mkdtemp/mkstemp(能指定临时文件名模板)。
内存流:fmemopen,把某段内存当做FILE流返回,然后进行I/O操作,一般用于创建字符串
相关文章推荐
- 应用领航:盘点那些年我们一起追过的OS
- Linux VS Unix:Linux欲一统天下 Unix不死
- 无奇不有!盘点各国自己开发的操作系统
- 可自定义oem的萝卜家园 Ghost XP 新春装机版 V200801 下载
- 看UNIX高手的10个习惯第1/2页
- Linux操作系统添加新硬盘方法
- Linux rdesktop操作系统下远程登录Windows XP桌面
- 32位操作系统认出超出4G内存的方法
- Linux rpm tar 操作系统下软件的安装与卸载方法
- 通过PHP修改Linux或Unix口令的方法分享
- mysql unix准换时间格式查找指定日期数据代码
- JavaScript 获取用户客户端操作系统版本
- jsp 获取客户端的浏览器和操作系统信息
- php strtotime 函数UNIX时间戳
- 安全检测Unix和Linux服务器安全设置入门精讲
- Windows 操作系统的安全设置
- PHP获取用户的浏览器与操作系统信息的代码
- Perl操作系统环境变量的脚本代码
- php根据操作系统转换文件名大小写的方法
- 开源操作系统和必备工具网站收集