第五章:标准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 已定向流不会改变 ...
随机推荐
- 免sudo使用docker
前沿:通过root安装完docker,在普通用户下执行docker相关命令的时候,报权限不足: 查看sock文件的权限: [hadoop@slave1 monitor]$ ll /var/run/do ...
- 简记webpack运行报错 Uncaught TypeError: self.postMessage is not a function
说好2017Fix的还是能重现,可能项目的版本比较旧了,简要记录解决办法 1.错误: index.js?bed3:67 Uncaught TypeError: self.postMessage is ...
- MAC将根目录文件夹的权限赋给用户
https://my.oschina.net/liujiest/blog/762004 1.sudu -i进入root模式(需输入密码) 2.chown -R 用户名 /文件夹名 sudo -i Pa ...
- P5663 加工零件
P5663 加工零件 题解 暴力搜索 搜索显然会TLE #include<iostream> #include<cstdio> #include<cstdlib> ...
- OpenJudge计算概论-奇数求和
/*=================================================== 奇数求和 总时间限制: 1000ms 内存限制: 65536kB 描述 计算非负整数 m 到 ...
- 【React自制全家桶】一、Webstrom+React+Ant Design+echarts搭建react项目
前言 一.React是Facebook推出的一个前端框架,之前被用于著名的社交媒体Instagram中,后来由于取得了不错的反响,于是Facebook决定将其开源.出身名门的React也不负众望,成功 ...
- angular绑定数据
Angular 中使用{{}}绑定业务逻辑里面定义的数据 <h1> Welcome to {{ title }}! /*引入title*/ </h1> export class ...
- angular项目目录结构分析
详情查看:https://www.angular.cn/guide/file-structure app.module.ts 定义 AppModule, 这个根模块会告诉 Angular 如何组装该应 ...
- 网络爬虫urllib:request之urlopen
网络爬虫urllib:request之urlopen 网络爬虫简介 定义:按照一定规则,自动抓取万维网信息的程序或脚本. 两大特征: 能按程序员要求下载数据或者内容 能自动在网络上流窜(从一个网页跳转 ...
- SQL语句里合并两个select查询结果
SQL UNION 操作符UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每条 ...