1.标准IO介绍
标准 I/O 库则是标准 C 库中用于文件 I/O 操作(譬如读文件、写文件等)相关的一系列库函数的集合
库文件<stdio.h>
文件IO和标准IO的区别:
1)标准IO是C库函数,文件IO是Linux系统调用
2)标准IO是文件IO封装而来,调用标准IO实际是调用文件IO完成实际操作
3)标准IO可移植性好,很多操作系统都实现了标准IO库,在不同系统中接口定义几乎一样
4)标准IO性能、效率优于文件IO,标准IO维护了自己的stdio缓冲区
2.FILE指针
与文件IO不同,调用open函数返回的不是文件描述符fd,而是指向FILE类型对象的指针,FILE 是一个结构体数据类型,它包含了标准 I/O 库函数为管理文件所需要的所有信息,包括用于实际I/O 的文件描述符、指向文件缓冲区的指针、缓冲区的长度、当前缓冲区中的字节数以及出错标志等。FILE数据结构定义在标准 I/O 库函数头文件 stdio.h 中。
3.标准输入,标准输出,标准错误
所谓标准输入设备指的就是计算机系统的标准的输入设备,通常指的是计算机所连接的键盘;而标准输出设备指的是计算机系统中用于输出标准信息的设备,通常指的是计算机所连接的显示器;标准错误设备则指的是计算机系统中用于显示错误信息的设备,通常也指的是显示器设备
标准输出文件和标准错误文件都对应终端的屏幕,而标准输入文件则对应于键盘。
在标准 I/O 中,可以使用 stdin、stdout、stderr 来表示标准输入、标准输出和标准错误。
4.fopen函数
函数原型
FILE *fopen(const char *path,const char *mode);
path:文件路径,可以是绝对路径和相对路径
mode:读写权限,一个字符串
返回值:成功->返回指向FILE类型对象的指针,与打开或者创建的文件相关联
失败->返回NULL,并设置errno指示错误原因
无法手动指定文件的权限
5,fclose函数
函数原型
int fclose(FILE *stream);
stream:是FILE类型的指针
返回值:成功->0
失败->EOF,并且会设置errno来指示错误
6. fread和fwrite函数
函数原型
size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream);
ptr: fread()将读取到的数据存放在参数指针ptr里,指向缓冲区
size:fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大小为 nmemb * size个字节。
nmemb:数据项个数
stream:FILE指针
返回值:成功则返回nmemb,到达文件末尾则返回值小于nmemb,错误还是到达文件末尾通过ferror()和feof()判断
size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream);
ptr:将参数 ptr 指向的缓冲区中的数据写入到文件中。
size:参数 size 指定了每个数据项的字节大小,与 fread()函数的 size 参数意义相同
nmemb:参数 nmemb 指定了写入的数据项个数,与 fread()函数的 nmemb 参数意义相同。
stream:FILE 指针
返回值:调用成功时返回读取到的数据项的数目,如果发生错误,则 fwrite()返回的值将小于参数 nmemb(或者等于 0)。
7. fseek函数
函数原型
int fseek(FILE *stream,long offset,int whence);
8. ftrll函数
获取当前文件的读写位置偏移量
函数原型
long ftrll(FILE *stream);
返回值:成功则返回偏移量,失败返回-1,errno以指示错误原因
9. 检查或复位状态
9.1 feof函数
用于测试stream所指文件的end-of-file标志是否被设置,被设置则返回非零值,没有被设置则返回0
函数原型
int feof(FILE *stream)
示例:
if(feof(file)){
/*到达文件末尾*/
}else{
/*未到达文件末尾*/
}
9.2 ferror函数
用于测试参数stream所指文件的错误标志,有错误返回非零值,没有错误返回0
if(ferror(file))
{
/*发生错误*/
}
else{
/*未发生错误*/
}
9.3 clearerr函数
清楚错误标志,调用feof和ferror发生错误时产生了错误标志,为了避免下次校验时使用了上次的错误标志,需要调用clearerr清楚标志
10.格式化I/O
10.1 格式化输出
共有参数format,用于指定后续的参数如何进行格式转换
printf()函数用于将格式化数据写入到标准输出;
dprintf()和 fprintf()函数用于将格式化数据写入到指定的文件中,两者不同之处在于,
fprintf()使用 FILE 指针指定对应的文件、而dprintf()则使用文件描述符 fd 指定对应的文件;
sprintf()、snprintf()函数可将格式化的数据存储在用户指定的缓冲区 buf 中
10.1.1 printf
10.1.2 fprintf
10.1.3 dprintf
10.1.4 sprintf
需要注意可能会引起buf指定的缓冲区溢出
10.1.5 snprintf
10.1.6 格式控制字符串format
10.2 格式化输入
scanf()函数可将用户输入(标准输入)的数据进行格式化转换;
fscanf()函数从 FILE 指针指定文件中读取数据,并将数据进行格式化转换;
sscanf()函数从参数 str 所指向的字符串中读取数据,并将数据进行格式化转换。
10.2.1 scanf
10.2.2 fscanf
10.2.3 sscanf
11. I/O缓冲
11.1 文件内核缓冲
11.1.1 刷新文件IO内核缓冲
- fsync()函数
将fd所指文件内容数据同元素数据写入磁盘(元数据类似于inode节点包含的文件大小,文件名等信息)
-
fdatasync()函数
同fsync,但 fd 所指文件的内容数据和元数据不会写入磁盘
-
sync()函数 数据同步
- 控制文件I/O内核缓冲的标志
11.2 直接IO
绕过内核缓冲,直接将文件数据传递到磁盘空间
- O_DIRECT标志
- 直接IO的对齐限制
11.3 stdio缓冲
-
标准IO的stdio缓冲
标准 I/O 所维护的 stdio 缓冲是用户空间的缓冲区,当应用程序中通过标准 I/O 操作磁盘文件时,为了减少调用系统调用的次数,标准 I/O 函数会将用户写入或读取文件的数据缓存在 stdio 缓冲区,然后再一次性将 stdio 缓冲区中缓存的数据通过调用系统调用 I/O(文件 I/O)写入到文件 I/O 内核缓冲区或者拷贝到应用程序的 buf 中。
11.3.1 setvbuf()函数
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
buf:不为NULL则指向size大小的内存区域作为该文件的stdio缓冲区
mode:用于指定缓冲区的缓冲类型
-
刷新stdio缓冲区 | 关闭文件时刷新stdio缓冲区
-
程序退出时刷新 stdio 缓冲区