第五章:标准I/O库
本章用于解析C语言标准I/O库,之所以在UNIX类系统的编程中会介绍C语言标准库,主要是因为UNIX和C之间具有密不可分的关系。
标准I/O库相比于操作系统的I/O库,具有更高的效率和可移植性,前者是因为标准I/O库提供了缓冲和块长度优化功能,后者是因为使用标准I/O库的代码不仅能在各UNIX系统上移植,也能在支持标准C的非UNIX系统上移植。
一、基本概念
流和FILE对象
UNIX系统I/O是建立在文件描述符的抽象概念上的,而标准I/O库则是建立在流的概念上的。当使用标准I/O库打开一个文件进行读写时,会创建一个流,该流与将要打开的文件进行关联,通过对抽象流的读写来间接读写文件。
标准输入、标准输出和标准错误
UNIX系统的shell中会默认为进程打开3个文件描述符:标准输入0、标准输出1和标准错误2。但它们是文件描述符的可阅读宏,ISO C标准I/O是无法使用的,为此ISO C标准I/O定义了三个另外的名字来引用它们,分别是:stdin、stdout、strerr。它们在头文件<stdio.h>中被定义。实际上STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO分别对应stdin、stdout、strerr。
缓冲
对于UNIX系统来说,标准I/O库最终是建立在系统调用的read()和write()上的。而UNIX系统的read()和write()是不带缓冲的。为了提供效率,标准I/O库提供了缓冲管理。
对于需要立即执行完成的标准读写操作,我们可以强制使用fflush()函数来刷新流的缓冲区。其函数声明如下:
- #include <stdio.h>
- int fflush(FILE *__stream);
- /* 例子 */
- fflush(stream);
二、标准I/O函数
- #include <stdio.h>
- /* 1. 打开流 */
- FILE *fopen(const char * __filename, const char * __modes);
- FILE *freopen(const char * __filename, const char * __modes, FILE * __stream);
- FILE *fdopen(int __fd, const char *__modes);
- /* fopen()用于打开指定路径的文件 */
- /* freopen()在指定流上关联指定的文件。如流已经打开,则重新打开;如流已定向,则清除定向。该函数通常用来重定向标准输入、标准输出和标准错误 */
- /* fdopen()用于将一个已有的文件描述符与一个标准I/O流关联。该函数常在创建管道或者网络socket得到的描述符上 */
- /* 2. 读/写流 */
- /* 2.1 字节I/O */
- int getc(FILE *__F);
- int fgetc(FILE *__F);
- int getchar(void);
- /* 这三个函数一次只读取一个unsigned char,然后转换为int,在读取一个字符后,流自动移动到下一个字符,然后再次调用函数时会返回相对于上一次字符的下一个位置上的字符 */
- int putc(int __c, FILE *__F);
- int fputc(int __c, FILE *__F);
- int putchar(int __c);
- /* 这三个函数成功返回__c,失败返回NULL。这三个函数一次只写入一个unsigned char,如果传递的值超过256的int类型实参给函数,那么超出范围的会被截断 */
- /* 2.2 行I/O,遇到换行符位置 */
- char *gets(char *__s);
- char *fgets(char* __s, int __n, FILE* __F);
- /* gets()函数建议不要使用,因为此函数会导致缓存区溢出 */
- int fputs(const char* __s, FILE* __F);
- int puts(const char* __s);
- /* 2.3 二进制I/O */
- size_t fread(void* __ptr, size_t __size, size_t __n, FILE* __F);
- size_t fwrite(const void* __ptr, size_t __size, size_t __n, FILE* __F);
- /* 这两个函数的返回值都是读或写的对象数量。参数中的__size是对象的大小,即sizeof计算得到的大小;__n是对象的数量 */
- /* 3. 定位流 */
- int fseek(FILE *__F, long int __off, int __whence);
- /* 4.关闭流 */
- int fclose(FILE *__F);
代码中的fopen()函数的第二个参数有以下几种模式:
r 以只读方式打开文件,该文件必须存在
r+ 以读/写方式打开文件,该文件必须存在
rb+ 以读/写方式打开一个二进制文件,只允许读/写数据
rt+ 以读/写方式打开一个文本文件,允许读和写
w 打开只写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件
w+ 打开可读/写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件
a 以附加的方式打开只写文件。若文件不存在,则会创建该文件;如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF 符保留)
a+ 以附加方式打开可读/写的文件。若文件不存在,则会创建该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF符不保留)
wb 以只写方式打开或新建一个二进制文件,只允许写数据
wb+ 以读/写方式打开或新建一个二进制文件,允许读和写
wt+ 以读/写方式打开或新建一个文本文件,允许读和写
at+ 以读/写方式打开一个文本文件,允许读或在文本末追加数据
ab+ 以读/写方式打开一个二进制文件,允许读或在文件末追加数据
常用的有r+,rt+,at+等
代码中的gets()会导致缓存区溢出,尽量不要使用。同样会导致缓存区溢出的函数有strcpy()、strcat()等
示例代码:
- FILE *stream = NULL;
- char buf[] = "Hello World\n";
- int ret = ;
- stream = fopen("a.txt", "w+");
- fwrite(buf, sizeof(char), strlen(buf), stream);
- fseek(stream, , SEEK_SET); /* whence可选为SEEK_SET、SEEK_CUR、SEEK_END */
- memset(buf, , sizeof(buf));
- ret = fread(buf, sizeof(char), sizeof(buf), stream);
- if (ret) {
- printf("Read %d Bytes From a.txt, Content: %s\n", ret, buf);
- }
- fclose(stream);
下一章 第七章:进程环境
第五章:标准I/O库的更多相关文章
- 《UNIX环境高级编程》(APUE) 笔记第五章 - 标准I/O库
5 - 标准I/O库 Github 地址 1. 标准 I/O 库作用 缓冲区分配 以优化的块长度执行 I/O 等 使用户不必担心如何选择使用正确的块长度 标准 I/O 最终都要调用第三章中的 I/O ...
- UNIX系统高级编程——第五章-标准I/O库-总结
基础: 标准I/O库在ANSI C中定义,可移植在不同的系统 文件指针(FILE):标准I/O库操作的不是文件描述符,而是流.FILE文件指针包含的是维护流所需的信息 通过函数fileno获取流的文件 ...
- 《APUE》-第五章标准IO库
大多数UNIX应用程序都使用I/O库,本章说明了该库所包含的所有函数,以及某些实现细节和效率方面的考虑.同时需要重点关注标准I/O使用了缓冲的技术,但同时也是因为它的出现,产生了很多细节上的问题. 流 ...
- UNIX环境高级编程 第5章 标准I/O库
本章是关于C语言标准I/O库的,之所以在UNIX类系统的编程中会介绍C语言标准库,主要是因为UNIX和C之间具有密不可分的关系.由于UNIX系统存在很多实现,而每个实现都有自己的标准I/O库,为了统一 ...
- 第五章 标准I/O
5.1 引言 本章说明标准 I/O 库.因为不仅在 UNIX 上,而且在很多操作系统上都实现了此库,所以它由 ISO C 标准说明. 标准 I/O 库处理很多细节,例如缓冲区分配,以优化长度执行 I/ ...
- apue学习笔记(第五章 标准I/O)
本章讲述标准I/O库 流和FILE对象 对于标准I/O库,它们的操作是围绕流进行的.流的定向决定了所读.写的字符是单字节还是多字节的. #include <stdio.h> #includ ...
- APUE之第5章——标准I/O库
一.知识回顾:文件I/O 文件 I/O 是不带缓冲的 I/O(unbuffered I/O),指每个 read 和 write 都调用内核中的一个系统调用. 对于内核而言,所有打开的文件都通过文件描述 ...
- Python爬虫学习==>第五章:爬虫常用库的安装
学习目的: 爬虫有请求库(request.selenium).解析库.存储库(MongoDB.Redis).工具库,此节学习安装常用库的安装 正式步骤 Step1:urllib和re库 这两个库在安装 ...
- 第5章标准I/O库总结
1 fwide函数试图设置流的定向(流的定向决定了读写单字节还是多字节字符) int fwide(FILE *fp,int mode) 宽定向返回正值,字节定向返回负值,为定向返回0 已定向流不会改变 ...
随机推荐
- 小程序web-view的使用,跳转到外部链接~
先说一下需求,要点击榜单,跳到我们的移动web的项目的榜单页,这个不是小程序的哦,就是网页版的. 榜单的html代码: <view class="nav" hover-cla ...
- 怎么在for循环中新建出不同的list
public static void main(String[] args) { List<Integer> list = Arrays.asList(1, 1, 1, 1, 1, 3, ...
- Flutter移动电商实战 --(42)详细页_UI主页面架构搭建
详细分成六大部分拆分开 body里面用FutureBuilder异步加载. FutureBuilder里面的furure属性这里用一个方法,必须返回的也是future 把我们的方法修改为返回的类型为F ...
- Java打印素数(质数)
要求:打印 2 - 100000 当中的素数与非素数.(素数定义:在大于1的自然数中,除了1和它本身以外不再有其他因数) 1. 常规方式——对正整数n,如果用2到 之间的所有整数去除,均无法整除,则 ...
- Celery如何修复Python的GIL问题
小结: 1. Celery如何修复Python的GIL问题https://python.freelycode.com/contribution/detail/346 最近,我重读了Glyph写的Uny ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#elif(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#elif(C# 参考) 1.返回顶部 1. #elif(C# 参考) 2015/07/20 #elif 可以创建复合条件指令. ...
- Java 数组元素逆序Reverse的三种方式
Java 数组元素逆序Reverse的三种方式 本文链接:https://blog.csdn.net/xHibiki/article/details/82930521 题目 代码实现 说明 int ...
- LinearGradient线型渐变效果
public LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, TileM ...
- webdriver报不可见元素异常方法总结
最近一直在学Selenium相关东西,学到webdriver这块,出现报不可见元素异常方法异常,后来网上找了好多相关资料都没搞定,也没看明白,最后发现是xpath中写了calss属性有问题.现在把学习 ...
- Python中的logging模块就这么用
Python中的logging模块就这么用 1.日志日志一共分成5个等级,从低到高分别是:DEBUG INFO WARNING ERROR CRITICALDEBUG:详细的信息,通常只出现在诊断问题 ...