嵌入式学习-I/O-Day01
IO介绍
IO分类
文件IO
标准IO
标准IO的调用逻辑
标准IO缓存机制
标准IO的特点 *
流
定义
流的分类
流指针FILE *
缓存区的分类 *
全缓存—》基于文件
行缓存-》基于终端stdin/stdout
不缓存:stderr
标准IO的函数接口
fopen 打开文件
fclose 关闭文件
perror
fgetc 读一个字符
fputc 写单个字符
fgets 获取字符串
fputs 输入字符串
fprintf
IO介绍
I: input:输入
O:output:输出
对文件的输入和输出:输入-》写文件:将内存当中的内容,写入到文件中。
输出-》读文件:将文件中的内容读取到内存。
linux下一切皆文件
文件类型(bcd-lsp)
- b(Block Device File):块设备文件
- C(Character Device File):字符设备文件
- d(Directory): 目录文件
- -:普通文件
- L(Link):链接文件
- s(socket):套接字文件:用于网络通信(网络编程)
- P(pipe):管道文件:用于进程间的通信方式
IO分类
文件IO
内核向上提供的输出输出函数接口,叫做系统调用函数接口。基于内核,内核不同,系统调用函数接口不同,文件IO不同操作系统函数接口不通用。可移植性较差。
标准IO
标准IO是C库中定义的一组用于输入输出的函数接口。不同的操作系统只要移植了C库就可以使用,它是在系统调用之前做了一个二次封装,相当于是间接的进行了系统调用。可移植性强,可以在不同的系统环境下进行使用。
标准IO的调用逻辑
标准IO读/写操作
if(是linux操作系统)
{
调用linux的系统函数(文件io)
}
if(是Windows操作系统)
{
调用Windows的系统函数(文件io)
}
if(是ios操作系统)
{
调ios用的系统函数(文件io)
}
标准IO缓存机制
标准IO在系统调用之前作了二次封装增加了缓存机制,减少了系统调用的次数,提高了程序的效率。
缓存机制
正常调用——》应用层读写文件——》调用内核层的函数接口—》内核层和硬件层进行交互-》拿到数据返回给应用层。
带有缓存机制-》应用层读写文件-》调用内核层的函数接口-》内核层和硬件层进行交互-》拿到数据返回给缓存区-》每次调用从缓存区当中拿数据。
标准IO的特点 *
- 标准IO是C库中提供的一组专门用于输入输出的函数接口
- 标准IO不仅在Unix系统上,在很多操作系统上都实现了标准IO。
- 标准I/O通过缓冲机制减少系统调用,提高效率
- 标准I/O库的所有操作都是围绕流(stream)来进行的,在标准I/O中,流用FILE *来描述。
- 标准IO默认打开三个流:标准输入(stdin),标准输出(stdout),标准出错(stderr)。
流
定义
所有的I/O操作仅是简单的从程序移进或者移出,这种字节流,就称为流。
流的分类
文本流/二进制流
流指针FILE *
FILE* 是一个指向 FILE 结构体的指针,这个结构体由标准库定义,用于表示一个打开的文件或输入/输出流。
查看命令
输入1,点击回车
放到FILE上,按住CTRL + ] CTRL + [
缓存区的结束地址和起始地址
缓存区的分类 *
全缓存—》基于文件
刷新缓存的条件:1 程序正常退出(遇到return(main))
2 exit 刷新缓存区
3 关闭文件流
4 fflush:强制刷新缓存区
5缓存区满
行缓存-》基于终端stdin/stdout
刷新缓存的条件:1 程序正常退出(遇到return(main))
2 exit 刷新缓存区
3 关闭文件流
4 fflush:强制刷新缓存区
5缓存区满
6 \n刷新缓存区
不缓存:stderr
注意:缓存区只有在用的时候才会开辟。
示例代码:
- 程序正常结束刷新缓存区
2. 缓存区满
3. \n刷新
4.fflush刷新 man fflush
#include <stdio.h>
int fflush(FILE *stream);
功能:强制刷新缓存区
fflush(NULL)//强制刷新所有缓存区。
参数:文件流
返回值:成功:0
失败:EOF(-1)更新errno
示例代码:
标准IO的函数接口
1. 打开文件,关闭文件(fopen,fclose)
2.读/写一个字符(fgetc fputc)
3. 读/写一个字符串(fgets fputs)
4.读/写一个二进制文件(fread fwrite)
5. 移动指针(fseek)
fopen 打开文件
头文件
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
功能:打开一个文件
参数:参数:path:打开的文件的路径
mode:打开方式
r:只读,文件指针定位到文件开头(有文件)
r+:可读可写,文件指针定位到文件开头(有文件)
w:只写,文件不存在创建,存在清空,文件指针定位到文件开头
w+:可读可写,文件不存在创建,存在清空,文件指针定位到文件开头
a: 只写,文件不存在创建,存在追加(到文件末尾)
a+:可读可写,文件不存在创建,存在追加(到文件末尾)
读文件指针定位到文件开头。
返回值:成功返回文件流指针
失败返回NULL,并且设置错误码
示例代码
问:一个任务找中,最多打开多少个文件?一个文件能不能重复的被打开(可)
运行结果:
最多打开1021+3个文件(1024)
注意:打开文件的个数属于有限资源,所以用完这个文件后记得及时关闭。
fclose 关闭文件
int fclose(FILE *stream);
功能:关闭文件
参数:
stream:流指针
返回值:成功0,失败-1,更新errno
用法:fclose(fp);
perror
#include <stdio.h>
#include <errno.h>
void perror(const char *s);
功能:根据errno的值获取错误信息,将信息输出到终端
参数:s:提示信息
返回值:成功0,失败-1
fgetc 读一个字符
int fgetc(FILE *stream);
功能:从文件中读一个字符
参数:
stream:流指针(从那个文件读)
返回值:成功返回读到字符的ascii值,失败返回或读到文件结尾返回-1.
示例代码:
fputc 写单个字符
#include <stdio.h>
int fputc(int c, FILE *stream);
功能:向指定文件中写入一个字符
参数:c:要写入字符的ASCII值
stream:流指针
返回值:写入字符ASCII值
失败返回:EOF
练习:用fputc和fgetc实现cp功能,将文件A中的内容放到文件B中
fgets 获取字符串
char *fgets(char *s, int size, FILE *stream);
功能:从文件中获取指定长度的字符串
参数: s:字符串存放的首地址
size:期望获取字符的个数
实际读size-1个字符,会自动补'\0',预留一个位置补'\0'.
文件中不满size-1个,有多少读多少,都会补'\0'.
当读到'\n',结束,不再读下一行内容,再次调用fgets继续从下一行开始读。
stream:文件流指针
返回值:
成功:返回获取成功字符串存放的首地址
失败或读到文件结尾返回NULL。
示例代码
fputs 输入字符串
int fputs(const char *s, FILE *stream);
功能:向指定文件中输入一串字符
参数:
s:输入字符串的首地址
stream:文件流指针
返回值:成功返回输出字符个数
失败返回EOF
fprintf
#include<stdio.h>
int fprintf(FILE *stream, const char *format, ...);
功能:向指定的文件以指定的格式写入数据
参数: stream :流指针
format:指定格式
...:多个参数
返回值:输出字符个数
失败返回:EOF
用法:
fprintf(fp, "hello world\n");
练习:用fgets实现wc –l的功能,文件名从命令行输入