01. 标准库函数与系统调用对比
系统调用 | 标准I/O库 |
---|---|
open/read/write/close | fopen/fread/fwrite/fclose |
文件描述符(fd) | 文件指针(FILE*) |
无缓冲,直接系统调用 | 自动缓冲管理 |
每次操作触发系统调用 | 减少系统调用次数 |
<fcntl.h> <unistd.h> | <stdio.h> |
系统调用封装层:
标准库函数在保证功能的前提下能够提升性能,扩展专属功能。
fopen与fread设计系统调用示例:
数据交换方式:
读写操作异同
系统调用族:
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
//文件定位
off_t lseek(int fd, off_t offset, int whence);
标准库函数:
//文件读写
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);
//文件查找
int fseek(FILE *stream, long offset, int whence);
long int ftell(FILE *stream);
void rewind(FILE *stream);
02. 系统调用文件操作
2.1 文件打开open()
系统调用 open()
向文件描述符fd
写入数据。
int open(const char *pathname, int flags, mode_t mode);
- 参数说明:
flags
:必选其一:O_RDONLY
,O_WRONLY
,O_RDWR
- 可选标志(一个
/
多个):O_CREAT
(创建),O_APPEND
(追加),O_TRUNC
(清空)等 mode
:文件权限umask
(八进制数,如0666)
2.2 文件关闭close()
int close(int fd);
2.3 文件写入write()
从用户空间buf
读取count
个字节数据写到fd
指向的文件中。
ssize_t write(int fd, const void *buf, size_t count);
- 参数:
fd
:文件描述符buf
:被写入的数据缓冲区count
:要写入的字节数
- 返回值:成功返回写入的字节数,失败返回-1
2.4 文件读取read()
从文件描述符fd
指向的文件中读取count
字节数据放到buf
缓冲区内。
ssize_t read(int fd, const void *buf, size_t count);
- 参数:
fd
:文件描述符buf
:读出的数据存放位置count
:要写入的字节数
- 返回值:成功返回写入的字节数,失败返回-1
ssize_t
指有一个-1
错误码表示失败的情况。
2.5 文件定位lseek()
off_t lseek(int fd, off_t offset, int whence);
- whence参数:
- SEEK_SET:文件开头
- SEEK_CUR:当前位置
- SEEK_END:文件结尾
返回值:成功: 返回新的offset
。失败:返回(off_t)-1
啊
文件操作基础流程: 打开文件 → 读写操作 → 关闭文件
03.C文件的打开与关闭
3.2 二进制文件语文本文件
如数字63,在文本文件中表示6和3两个ASCII字符表示
'6' → 0x36
'3' → 0x33
文件内容:36 33//与字符编码一致
而在二进制文件中将63直接转化成二进制形式
//在32位下,int类型,
//小端对齐(字节内部顺序不变,储存顺序与阅读顺序相反即:00 00 00 3F是我们转换的二进制内容)
//需考虑字节序/对齐
3F 00 00 00 // 63的十六进制是0x3F
3.2 文件的打开fopen()
//文件打开
FILE *fopen(const char *filename, const char *mode);
- 功能:打开文件并返回文件指针
- 参数:
pathname
:文件路径mode
:打开模式(“r”, “w”, “a”, “r+”, “w+”, "a+"等)
- 返回值:成功返回FILE指针,失败返回NULL
打开模式: 输出->到磁盘
模式字符串 | 含义 | 如果指定文件不存在 |
---|---|---|
“r” | 只读 - 打开文本文件输入数据 | 出错 |
“w” | 只写 - 创建文本文件输出数据 | 建立新文件 |
“a” | 追加 - 向文本文件尾添加数据 | 建立新文件 |
“rb” | 只读 - 打开二进制文件输入数据 | 出错 |
“wb” | 只写 - 创建二进制文件输出数据 | 建立新文件 |
“ab” | 追加 - 向二进制文件尾添加数据 | 建立新文件 |
“r+” | 读写 - 打开文本文件进行读写 | 出错 |
“w+” | 读写 - 创建新文本文件进行读写 | 建立新文件 |
“a+” | 读写 - 打开文本文件在文件尾读写 | 建立新文件 |
“rb+” | 读写 - 打开二进制文件进行读写 | 出错 |
“wb+” | 读写 - 创建新二进制文件进行读写 | 建立新文件 |
“ab+” | 读写 - 打开二进制文件在文件尾读写 | 建立新文件 |
注意:
w
系列模式("w"
,"w+"
,"wb"
,"wb+"
):强制清空。a
系列模式("a"
,"a+"
,"ab"
,"ab+"
):追加写入。r
系列模式("r"
,"r+"
,"rb"
,"rb+"
):保留内容(文件必须存在)
示例:fopen("log.txt", "r")
3.3 文件的关闭fclose()
int fclose(FILE *stream);
- 成功返回
0
,失败返回EOF
- 必须调用以避免资源泄漏
04. 文件顺序读写
4.1字符读写
int fgetc(FILE *stream); // 读取一个字符
int fputc(int c, FILE *stream); // 写入一个字符到流中
4.2字符串读写
int fputs(const char *str, FILE *stream); // 写入字符串到流中
特性:
- 函数在遇到第一个
\0
时就停止
char *fgets(char *str, int n, FILE *stream); // 读取n-1字符到str中,最后一个位置自动补`\0`
fgets
读取到换行符或n-1
个字符后停止- 自动添加
\0
终止符
4.3 格式化读写
int fprintf(FILE *stream, const char *format, ...); // 格式化写入到磁盘
将可变参数中的数据,按照编写的format
格式写入到strem
流(先缓存再刷新到磁盘)中。
stream
:目标文件(如stdout
、stderr
或FILE*
文件指针)format
:格式化字符串(类似printf
)...
:可变参数- 返回值:成功时返回写入的字符数,失败返回负值。
+--------------------------+ 格式化转换 +-------------------+ 写入文件
| 变量 (age, score,add) | ------------> | 格式化后的字符串 | ------------> log.txt
+--------------------------+ +-------------------+
int fscanf(FILE *stream, const char *format, ...); // 格式化读取内存
从strem
(文件流)中按照format
的格式匹配数据,转换数据并存储到变量当中。
stream
:源文件(如stdin
或FILE*
文件指针)format
:格式化字符串(指定如何解析数据)...
:可变参数(存储读取的数据)- 返回值:成功匹配的参数个数,失败或
EOF
时返回EOF(-1)
+-------------------+ 解析 & 转换 +---------------------+
| 文件内容 (字符串) | ------------> | 变量 (age, score,add)|
+-------------------+ +---------------------+
//将格式化数据写入字符串str
int sprintf(char *str, const char *format, ...);
//从字符串str中读取格式化输入 变量...
int sscanf(const char *str, const char *format, ...);
4.4 二进制读写
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数说明:
ptr
:指向要读写的数据的指针size
:单个元素字节数nmemb
:读写元素数量stream
: 文件指针
返回值:成功读写的元素个数
二进制写/读:stus
是一个结构体数组可做首地址类似于数组名。
05. 文件随机读写
5.1 fseek()
功能:根据文件指针位置和偏移量来定位文件指针,跳转到指定位置
int fseek(FILE *stream, long offset, int origin);
- 参数:
stream
:文件指针。offset
:偏移量(字节数)。origin
:基准位置,可选值:SEEK_SET
:文件开头。SEEK_CUR
:当前位置。SEEK_END
:文件末尾。
5.2 ftell()
功能:返回当前文件指针相对于起始位置偏移量
long ftell(FILE *stream);
5.3 rewind()
功能:让文件指针回到文件起始位置
void rewind(FILE *stream);