目录
1.打开文件
1.1 fopen函数原型
1.1.1 fopen函数
1.1.2 fopen函数原理
1.1.3 文本文件和二进制文件区别?
1.1.4 “r"模式和“rb”模式区别?
1.1.5 fopen函数使用示例
1.2 fdopen函数原型
1.2.1 fdopen函数
1.2.2 fdopen函数原理
1.2.3 fdopen函数使用示例
1.3 freopen函数原型
1.3.1 freopen函数
1.3.2 freopen函数原理
1.3.3 freopen函数使用示例
2.关闭文件
2.1 fclose函数原型
2.1.1 fclose函数
3.stdin,stdout,stderr介绍
1.打开文件
1.1 fopen函数原型
1.1.1 fopen函数
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
函数简介:fopen函数是 C 语言标准库中的一个函数,用于打开文件并返回一个文件指针。
函数参数:
pathname:字符串,表示要打开的文件名。
mode:字符串,表示打开文件的模式,具体设置方法参考表 1-1
表 1-1 fopen函数 mode参数参考表
函数返回值:
成功:返回文件指针。
失败:返回NULL,并设置errno。
1.1.2 fopen函数原理
图 1-1 fopen函数原理
调用fopen函数后,会在用户空间创建一个FILE对象,同时通过open系统调用在内核创建sturct file对象和struct inode对象,open系统调用原理参考:文件IO_打开和关闭文件(附Linux-5.15.10内核源码分析)
调用open成功后会返回一个fd(文件描述符),FILE对象的_fileno成员会记录该fd,_fileno是用户空间和内核空间数据交互的桥梁。
后续可以使用_fileno和文件IO系统调用直接和内核交互,也可以通过FILE文件指针和标准IO接口和内核交互。
1.1.3 文本文件和二进制文件区别?
图 1-2 文本文件和二进制文件
文本文件和二进制文件在存储层是一样的,都是以二进制形式存储。
不同的点在与逻辑层,文本文件通常为符合某种编码规范(如ASCII码)的文件,操作文本文件时,我们的输入输出数据要符合编码规范,这个是人为规定,如果不符合编码规范会出现乱码等现象。
二进制文件以值编码为规范,输入输出数据为数值(如十六进制)形式,以二进制模式读写文件,通常不容易出错,因为数据所见即所得,中间不存在转换环节。
1.1.4 “r"模式和“rb”模式区别?
、"r" 模式:以文本模式打开文件进行读取。在文本模式下,文件中的换行符会被转换为换行符(\n),而不同操作系统上的换行符可能有所不同(例如,Windows 上的换行符是 \r\n)。此模式适用于读取文本文件,例如纯文本文件、CSV 文件等。
"rb" 模式:以二进制模式打开文件进行读取。在二进制模式下,文件中的数据会以字节的形式读取,不会进行任何转换。此模式适用于读取二进制文件,例如图片、音频、视频等。
1.1.5 fopen函数使用示例
#define TEST_FILE "/tmp/test.txt"
int fopen_test() {
FILE *fp = fopen(TEST_FILE, "r+");
if (!fp) {
perror("fopen error");
return -1;
}
fclose(fp);
return 0;
}
1.2 fdopen函数原型
1.2.1 fdopen函数
#include <stdio.h>
FILE *fdopen(int fd, const char *mode);
函数简介:fdopen函数是C语言中用于将文件描述符(file descriptor)转换为文件指针(FILE*)的标准库函数之一。
函数参数:
fd:整数,表示要转换的文件描述符。
mode:参考fopen函数mode参数。
函数返回值:
成功:返回文件指针。
失败:返回NULL,并设置errno。
1.2.2 fdopen函数原理
图 1-3 fdopen函数原理
从fopen函数原理我们知道,用户空间和内核空间要交互数据又两种方法:
- 通过_fileno和文件IO系统调用直接和内核交互。
- 通过FILE文件指针和标准IO接口和内核交互。
fdopen函数主要作用为已通过open函数开的文件描述符再打开一个FILE文件指针,从而可以通过FILE文件指针和标准IO接口和内核交互。
1.2.3 fdopen函数使用示例
int fdopen_test() {
FILE *fp = fdopen(1, "w");
if (!fp) {
perror("freopen error");
return -1;
}
#define TEST_STRING "helloworld\n"
fwrite(TEST_STRING, strlen(TEST_STRING), 1, fp);
printf("let`s go\n");
fclose(fp);
return 0;
}
1.3 freopen函数原型
1.3.1 freopen函数
#include <stdio.h>
FILE *freopen(const char *pathname, const char *mode, FILE *stream);
函数简介:freopen函数是C语言中用于重新定向文件流的标准库函数之一。
函数参数:
pathname:字符串,表示要重新定向到的文件名。
mode:参考fopen函数mode参数。
stream:已打开的文件流指针,表示要重新定向的文件流。
函数返回值:
成功:返回文件指针。
失败:返回NULL,并设置errno。
1.3.2 freopen函数原理
图 1-4 freopen函数原理1
图 1-5 freopen函数原理2
freopen函数主要用来做文件重定向。
调用freopen函数之前,我们已经通过fopen函数打开了一个文件并返回FILE文件指针,也可以是默认打开的文件指针如:stdin,stdout,stderr。已打开的文件会在内核创建struct file和struct inode对象。
当调用freopen函数后,原先的FILE文件指针对应的内核struct file和struct inode会被新的struct file对象和struct inode对象替换,原先的对象会被关闭,此时我们操作FILE文件指针,我们操作的是新的struct file对象和struct inode对象。
freopen内部其实是通过dup3系统调用实现,dup3系统调用原理请参考:文件IO_复制文件描述符(附Linux-5.15.10内核源码分析)
1.3.3 freopen函数使用示例
int freopen_test() {
FILE *fp = freopen("test.log", "w", stdout);
if (!fp) {
perr string-literal r");
retu
} Type: char[12]
Size: 12 bytes
printf("_fileno:%d\n", fp->_fileno);
fclose(fp);
return 0;
}
2.关闭文件
2.1 fclose函数原型
2.1.1 fclose函数
#include <stdio.h>
int fclose(FILE *stream);
函数简介:fclose 函数是 C 语言标准库中的一个函数,用于关闭文件指针所关联的文件。
函数参数:
stream:要关闭的文件指针。
函数返回值:
成功:返回0。
失败:返回EOF(-1)。
fclose 函数会执行以下操作:
- 将缓冲区的内容刷新到磁盘中。
- 关闭文件描述符。
- 释放与文件相关的资源。
注意事项:
- 在使用完文件指针后,应该及时使用 fclose 函数关闭文件,以避免资源泄漏。
- 在关闭文件前,应确保文件指针有效,即不为 NULL。
- 关闭文件后,不要再使用已关闭的文件指针进行文件操作,否则会导致未定义的行为。
3.stdin,stdout,stderr介绍
图 3-1 stdin,stdout,stderr原理
Linux 系统使用三个标准流来处理数据:stdin(标准输入)、stdout(标准输出)和stderr(标准错误)。
Linux系统默认会打开stdin,stdout,stderr FILE文件指针,不需要用户程序主动打开。
stdin,stdout,stderr和普通的FILE没有什么区别,主要区别在于内核空间struct inode对应的文件类型不一样。
- 标准输入(stdin)
标准输入通常表示为文件描述符 0。 它用于接收输入数据。 在命令行环境下,默认情况下与键盘绑定,用于从键盘读取用户输入。 在程序中,可以使用 stdin 来读取用户输入的数据。
- 标准输出(stdout)
标准输出通常表示为文件描述符 1。 它用于输出程序的结果或信息。 在命令行环境下,默认情况下与终端绑定,将结果或信息显示在屏幕上。 在程序中,可以使用 stdout 来输出结果或信息。
- 标准错误(stderr)
标准错误通常表示为文件描述符 2。 它用于输出程序的错误信息、警告或调试信息。 与标准输出不同,标准错误专门用于输出与程序执行相关的错误信息。 在命令行环境下,默认情况下也与终端绑定,将错误信息显示在屏幕上。 在程序中,可以使用 stderr 来输出错误信息。