C 语言文件读写操作
前言
#include <stdio.h>
int main() {
FILE * file = fopen("hello.txt", "rw"); //使用fopen函数来打开一个文件
}
当我们在Clion中输入上述代码时,系统会友情提示我们需要在括号里填写两个特殊变量,让我们来认识一下它们吧!
首先,让我介绍给大家主角之一,__filename
,这是一个包含文件路径的字符串常量,它告诉计算机我们要读取或写入哪个文件。你可以将其视为文件的身份证,因为它唯一地标识了文件的位置和名称。在填写这个参数时,你可以指定相对路径或绝对路径,让计算机准确找到目标文件。
接下来,让我们认识另一个关键角色,__mode
,这是一个代表访问模式的字符串常量。它告诉计算机我们要以何种方式打开文件,以便进行读取或写入操作。你可以将其视为文件的访问权限,因为它决定了我们能否读取、写入或创建文件。常见的访问模式包括只读(“r”)、写入(“w”)和追加(“a”),当然还有其他更多选项供你探索。
所以,当我们在Clion中填写这两个参数时,我们实际上在向计算机提供了必要的信息,告诉它我们要处理哪个文件以及以何种方式进行操作。这让计算机能够准确理解我们的意图,让我们在文件读写的舞台上自如驰骋!
- 第一个参数:文件的名称,这里我填写的是相对路径(在
cmake-build-debug
文件下),也可以写成绝对路径(win系统带上盘符) - 第二个参数:打开文件的模式,其中模式有以下这些(平时主要使用读写操作,因此
r
和w
用的比较多):
模式字符串 | 含义 |
---|---|
“r” | 以读模式打开文件 |
“w” | 以写模式打开文件,把现有文件的长度截为0,如果文件不存在,则创建一个新文件 |
“a” | 以写模式打开文件,在现有文件末尾添加内容,如果文件不存在,则创建一个新文件 |
“r+” | 以更新模式打开文件(即可以读写文件)该文件必须存在 |
“w+” | 以更新模式打开文件(即可以读写文件),如果文件存在,则将其长度截为0;如果文件不存在,则创建一个新文件 |
“a+” | 以更新模式打开文件(即,读写),在现有文件的末尾添加内容,如果文件不存在则创建一个新文件;可以读整个文件,但是只能从末尾添加内容 |
“rb”,“wb”,“ab”,“ab+”,“a+b”,“wb+”,“w+b” | 与“a+”模式类似,但是以二进制模式打开文件而不是以文本模式打开文件 |
具体的不同打开模式会影响到后续的操作,我们后面再说。这里我们使用r
表示可读。
读文件
截止到目前为止,这样我们就成功打开了这个文件,那么如何对文件进行读取操作呢?我们可以使用getc
来快速读取文件中的字符,与getchar
不同的是,getchar
是在控制台实现输入,而getc
是文件的输入:
#include <stdio.h>
int main(){
FILE* file = fopen("hello.txt", "r");
if(file != NULL){
printf("文件打开成功!\n");
int c;
while ((c = getc(file)) != EOF){
putchar(c);
}
fclose(file); //fclose用于关闭文件
printf("\n");
printf("文件已关闭!\n");
} else{
puts("文件打开失败!");
}
}
当然,如果文件不存在或者文件打开失败,getc
函数可能会返回一个空指针。因此,我们需要进一步判断,确保文件操作的顺利进行。此外,务必记得在使用完文件后关闭它,释放资源,否则该文件将一直被占用,其他人将无法调用它。因此,合理的操作应包括打开文件、读取文件内容,并在完成后及时关闭文件,这样才能保持系统的正常运行。
写文件
那么读取文件我们知道了,写入呢?写入我们同样可以使用putc
来完成:
#include <stdio.h>
int main() {
FILE * file = fopen("hello.txt", "w"); //注意这里需要修改为写模式
if(file != NULL) {
for (int i = 0; i < 10; ++i)
putc('A' + i, file); //从A开始依次写入10个字符
fclose(file);
} else{
puts("文件打开失败!");
}
}
细心的读者可能会注意到,在开始时我们向.txt
文本文件中写入了"Hello World!"的内容,但现在发现文本内容已经被覆盖了。那么如果我们希望在之前的文本内容后面继续添加内容,我们应该如何操作呢?
这就是时候展示前面提到的文件打开模式的作用了!在这种情况下,我们可以选择以追加模式(a
)打开文件,然后再次运行代码。
通过以追加模式打开文件,我们可以将新的内容添加到文件的末尾,而不会覆盖之前的内容。这样,我们就可以在文件中持续记录并保存我们想要添加的内容,而不会丢失之前的数据。
因此,记住在打开文件时,根据需要选择适当的模式,以确保我们的操作与期望一致,并且文件内容能够得到正确的追加。
FILE * file = fopen("hello.txt", "a"); //注意这里需要修改为能从末尾添加内容
补充内容
不过这里要补充一下,文件的读写实际上并不是直接对文件进行操作的,在这之间还有一个缓冲区:
我们经常在别人的代码中常常看见这样一行代码fflush(file);
,咱也不知道为什么要这行代码,只知道使用fflush来刷新缓冲区,那么究竟是为什么呢?这个就和缓冲区有关了。
我们所有的读操作,首先是从文件读取到缓冲区中,再从缓冲区中读取到程序中的;写操作就是先写入到缓冲区,然后再从缓冲区中写入到文件中。这样做的目的是,因为内存和硬盘的速度差距有点大,为了解决这种速度差异导致的性能问题,所以设定一个缓冲区,这样就算速度不一样,但是内容被放在缓冲区中慢慢消化就没问题了。
虽然缓冲区能够解决这些问题,但是也会带来一些不便之处,比如下面的例子:
#include <stdio.h>
int main() {
FILE * file = fopen("hello.txt", "a+"); //注意这里需要修改为写模式
if(file != NULL) {
while (1) {
int c = getchar(); //不断从控制台读取字符
if(c == 'q') break;
putc(c, file); //写入到文件中
}
fclose(file);
}
}
我们发现当我们敲了一个字符之后,可能并不会马上更新到文件中,这就是由于缓冲区没有及时同步到文件中,所以我们需要调用一个函数来刷新缓冲区,将那些缓冲区的没有同步的数据全部同步到文件中:
#include <stdio.h>
int main() {
FILE * file = fopen("hello.txt", "a+");
if(file != NULL) {
while (1) {
int c = getchar();
if(c == 'q') break;
putc(c, file);
fflush(file); //使用fflush来刷新缓冲区
}
fclose(file);
}
}
执行上述代码,然后重新打开hello.txt
文件,可以看见从控制台输入的内容立马就写入到了文本文件中去了。
感谢阅读!掌握C语言文件读写操作,编程之旅更进一步!💻🚀