首页 > 代码库 > 读书笔记-APUE第三版-(5)标准IO库
读书笔记-APUE第三版-(5)标准IO库
ISO C标准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操作,一般用于创建字符串
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。