这篇博客和大家分享关于C语言文件操作方面的知识,相互交流,共同进步
目录
一、什么是文件?
我们前面写的代码里面都在使用 “变量”,或者说在使用内存
内存特点
容量小,速度块,断电之后数据丢失,比较贵
但是内存不能满足我们所有的使用场景。我们在有的时候也希望存储容量大一些,速度稍慢点也没太大关系,希望数据能够持久存储,这个时候我们用到外存,比如存在硬盘里面
外存特点
容量大,速度慢,断电之后数据仍存在,相比内存便宜一些
那么我们如何让数据在外存上存储呢? 关键就是通过文件
文件的路径
我们电脑上有很多的文件, 那么操作系统是如何来管理文件呢?这里关键就是路径
eg.
E:\嵌入式开发学习\开发环境配置2021.docx
这是我电脑上的开发环境配置2021.docx这个文件的路径
注意:同一个机器上, 每个文件的路径一定都是不相同的
文件名后缀
文件名后缀也叫做扩展名
有的人可能发现自己电脑上的文件并不能看见扩展名,这是因为你的电脑将后缀名隐藏了,可通过以下方式显示扩展名
这样就可以看到你的文件扩展名了
扩展名作用:
- 描述这个文件里的数据格式大概是啥样的
- 这个文件应该使用那个程序来打开
文件分类
我们这里讨论的就是数据文件
二、在C语言里面如何操作文件呢?
标准库里面还提供了一个FILE结构体用来描述一个文件
文件是存储在磁盘上的,要想直接操作磁盘,不太容易,因此操作系统就进行了封装。打开文件的时候其实就是在内存中创建了一个变量(FILE结构体变量),这个变量就和磁盘上的文件关联起来了,因此去读/写这个变量也就相当于是在读写文件了。
C 语言标准库里提供了一组操作函数(头文件都是<stdio.h>)
在这里我们学习一些主要的函数
- fopen
- fclose
- fwrite
- fread
三、fopen
用来打开文件
(其实就是在内存里创建了一个FILE结构体)
函数声明
FILE* fopen (const char* filename, const char* mode);
返回值:
FILE* : 文件指针
若打开文件失败(文件不存在或者没有读写权限),则返回NULL
参数:
filename: 这个参数表示一个文件路径
mode: 打开文件的方式
打开方式有以下几种基本用法
针对文本文件:
- "r" 读
- "w" 写. 清空原有的文件数据,从文件开头来写
- "a" 追加. 把数据写到原来文件的末尾
针对二进制文件打开:"rb", "wb", "ab"
代码
#include <stdio.h>
int main() {
FILE* fp = fopen("e:/test.txt", "r");
printf("%p\n", fp);
return 0;
}
用这个代码来打开d盘的test.c文件
运行结果:
可以看到打印结果为0,这是因为打开失败了,返回值为NULL(因为我的电脑e盘没有这样的文件)
对于打开文件的操作我们应该要进行判断,如下:
#include <stdio.h>
int main() {
FILE* fp = fopen("e:/test.txt", "r");
if (fp == NULL) {
perror("fopen");
return 0;
}
printf("打开文件成功\n");
return 0;
}
运行结果:
标准库里面有错误码(errno)来表示失败原因
在程序运行出现问题的时候就会有一个相应的错误码
可以用strerror这个函数来翻译错误码
用perror这个函数可以很方便的打印错误码
下面我在e盘创建一个text.txt文件来看看
四、fclose
这个函数用来关闭文件
为什么要关闭文件?
这和内存泄漏类似,如果我们动态开辟的内存不释放,那么就会造成内存泄漏
如果fopen之后,没有进行fclose,就可能会触发文件资源泄漏(一个程序能同时打开的文件数量也是有限的),如果一直打开文件,而不关闭的话,那么打开到一定程度就无法再继续打开了(这一一个非常严重的问题)
函数声明
int fclose (FILE* stream);
返回值:
若成功关闭文件,返回0,否则返回EOF(-1)
参数:
stream: fopen返回的结果
如下代码:
#include <stdio.h>
int main() {
FILE* fp = fopen("e:/test.txt", "r");
if (fp == NULL) {
perror("fopen");
return 0;
}
printf("打开文件成功\n");
fclose(fp);
return 0;
}
运行结果:
五、 fread
读文件
(实际就是将磁盘中的数据拷贝到内存中)
函数声明
size_t fread (void* ptr, size_t size, size_t count, FILE* stream);
返回值:
实际读取成功的元素个数
参数:
ptr: 读文件就是将磁盘中的数据拷贝到内存中,ptr就指向这块内存空间
size: 每个元素多大
count: 要拷贝多少个元素
stream: 传入fopen返回的结果,找到对应文件在磁盘上的具体位置
如下代码:
#include <stdio.h>
int main() {
FILE* fp = fopen("e:/test.txt", "r");
if (fp == NULL) {
perror("fopen");
return 0;
}
printf("打开文件成功\n");
char buffer[1024] = { 0 };
size_t count = fread(buffer, 1, 100, fp);
printf("%d\n", count);
printf("%s\n", buffer);
fclose(fp);
return 0;
}
在test.txt文件中已经存入数据"hello"
运行结果:
通过这个代码进行了打开文件,然后从文件中读取100个元素,每个元素1个字节大小,打印成功读取到的元素个数,并将buffer中的内容打印出来
六、fwrite
写文件
(将内存中的数据拷贝到磁盘中)
函数声明
size_t fwrite (const void* ptr, size_t size, size_t count, FILE* stream);
返回值:
size_t类型, 表示成功写入的元素个数
参数:
ptr: 将内存中的数据拷贝到磁盘中,ptr指向这个内存空间
size: 一个元素的大小是size
count:一共count个元素
stream: 传入fopen返回的结果,找到对应文件在磁盘上的具体位置
代码演示:
int main() {
FILE* fp = fopen("e:/test.txt", "w");
if (fp == NULL) {
perror("fopen");
return 0;
}
printf("文件打开成功\n");
char buffer[1024] = "success";
size_t count = fwrite(buffer, 1, strlen(buffer), fp);
printf("%d\n", count);
return 0;
}
运行结果:
此时就可以看到success已经存到了test.txt文件中
那么下面我们再运行一次以下程序:
#include <stdio.h>
int main() {
FILE* fp = fopen("e:/test.txt", "w");
if (fp == NULL) {
perror("fopen");
return 0;
}
printf("文件打开成功\n");
return 0;
}
打开test.txt
发现文件在只打开文件的代码执行之后,文件被清空了
注意
如果不想清空原有的数据,一定要谨慎使用"w"方式打开
七、fprintf
将数据写到文件里面(格式化写)
请看以下代码:
#include <stdio.h>
int main() {
FILE* fp = fopen("e:/test.txt", "w");
if (fp == NULL) {
perror("fopen");
return 0;
}
printf("文件打开成功\n");
fprintf(fp, "ret = %d", 2);
return 0;
}
运行结果:
可以看到将数据写到了文件中
八、fscanf
格式化读
接着上面fprintf的操作来
将代码修改如下:
int main() {
FILE* fp = fopen("e:/test.txt", "r");
if (fp == NULL) {
perror("fopen");
return 0;
}
printf("文件打开成功\n");
int ret = 0;
fscanf(fp, "ret = %d", &ret);
printf("%d\n", ret);
return 0;
}
运行结果:
成功从文件中读到了数据
九、sscanf
从一个字符串里面解析出内容
如下代码:
#include <stdio.h>
int main() {
char ch[] = "ret = 2";
int ret = 0;
sscanf(ch, "ret = %d", &ret);
printf("%d\n", ret);
return 0;
}
运行结果:
成功从这个字符串中读出了结果
十、 sprintf
把一个格式化结果输出到字符串中
如下代码:
#include <stdio.h>
int main() {
char ch[50] = { 0 };
sprintf(ch, "ret = %d", 2);
printf("%s\n", ch);
return 0;
}
运行结果:
成功将格式化结果输出到字符串中
应用场景
针对字符串和数字(整数/浮点数)之间进行转换
1. 将字符串转换成整数
#include <stdio.h>
int main() {
char ch[] = "11";
char ch2[] = "12";
int num1 = 0;
int num2 = 0;
sscanf(ch, "%d", &num1);
sscanf(ch2, "%d", &num2);
int ret = num1 + num2;
printf("%d\n", ret);
return 0;
}
这里就将ch和ch2里面的内容通过sscanf转换成了整数并进行相加
运行结果:
2. 将整数转换为字符串
#include <stdio.h>
int main() {
char ch[50] = { 0 };
int ret = 10;
sprintf(ch, "%d", ret);
printf("%s\n", ch);
return 0;
}
运行结果:
-----------------------------------------------------------------
-----------C语言 文件操作完结---------
欢迎大家关注!!!
一起学习交流 !!!
让我们将编程进行到底!!!
--------------整理不易,请三连支持------------------