C-文件操作实现数据持久化,帮你快速了解文件操作函数
创始人
2024-01-15 17:51:45
0

目录

一.了解文件

二.文件的打开和关闭

三.顺序读写文件函数

fputc字符输入函数

fgetc字符输入函数

 fputs文本行输出函数

 fgets文本行输入函数

fprintf格式化输出函数

fscanf格式化输入函数

fwrite二进制输出函数

fread二进制输入函数

四. 解析上述的流

 五.文件的随机读写

fseek

 ftell

rewind


一.了解文件

1.文件主要功能

  • 使用文件我们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化。
  • 在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显 示器上。
  • 其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理 的就是磁盘上文件。

2.什么是文件

磁盘上的文件是文件。

但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。

2.1程序文件

包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境 后缀为.exe)。

2.2数据文件

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件, 或者输出内容的文件。

 2.3 文件名

文件名包含3部分:文件路径+文件名主干+文件后缀

比如: c:\code\test.txt

二.文件的打开和关闭

以下所有讲的函数头文件都是:#include

1.文件指针

一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

我们可以创建一个FILE*的指针变量:

FILE* pf;//文件指针变量

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息, 使用者不必关心细节。

例如,VS2013编译环境提供的 stdio.h 头文件中有以下的文件类型申明:

 不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。

2.文件的打开和关闭

1.打开文件函数:

代码演示: 

FILE *pf = fopen("test.txt", "w");

文件名:

文件名分为两种形式:

1.绝对路径

文件路径+文件名主干+文件后缀

2.相对路径

文件名主干+文件后缀(也可以不加后缀)

相对路劲是在当前程序文件的文件夹下,去查找

 文件的打开方式:

文件使用方式含义如果指定文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件出错
“w”(只写)为了输出数据,打开一个文本文件建立一个新的文件
“a”(追加)向文本文件尾添加数据建立一个新的文件
“rb”(只读)为了输入数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文件建立一个新的文件
“ab”(追加)向一个二进制文件尾添加数据出错
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建议一个新的文件建立一个新的文件
“a+”(读写)打开一个文件,在文件尾进行读写建立一个新的文件
“rb+”(读写)为了读和写打开一个二进制文件出错
“wb+”(读写)为了读和写,新建一个新的二进制文件建立一个新的文件
“ab+”(读写)打开一个二进制文件,在文件尾进行读和写建立一个新的文件

返回:

正确代码书写:

//打开文件FILE *pf = fopen("test.txt", "w");//文件是有可能打开失败的,文件名出错,打开方式问题等if (NULL == pf){perror("fopen");return;}

只有打开文件就一定要搭配上判断

2.关闭文件函数

代码演示: 

fclose(pf);

正确的代码规范:

int main()
{//打开文件FILE *pf = fopen("test.txt", "w");//文件是有可能打开失败的,文件名出错,打开方式问题等if (NULL == pf){perror("fopen");return;}//写文件//……//关闭文件fclose(pf);pf = NULL;//防止再次使用此指针return 0;
}

三.顺序读写文件函数

  • 这里的输入是指把文件的数据输入到程序内存中
  • 输出指的是内存中的数据,输出到文件中

站在程序内存的角度,把文件想成平时打印的cmd黑框就好

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件

fputc字符输入函数

函数原型:

补充:输入流是什么 后面讲现在你们看一下代码就懂

函数代码: 

这是我当前文件下的一些文件,我讲利用打开方式自动创建一个文件

运行程序前的文件夹:

 代码:

#include
int main()
{//打开文件FILE* pf = fopen("test.txt", "w");if (NULL == pf){perror("fopen");return 1;}//写文件int i = 0;for (i = 0; i < 26; i++){fputc('a' + i, pf);//写入26个字母}//关闭文件fclose(pf);pf = NULL;return 0;
}

运行程序前的文件夹:

你们可以去看看是不是跟我打开的文件夹名相同,而且已经在里面写入了26个字母:

返回:

函数正常执行返回所写数据,字符返回对应ASII码值

发生写入错误返回EOF

fgetc字符输入函数

函数原型

返回:

函数正常执行返回所写数据,字符返回对应ASII码值

发生写入错误返回EOF

代码:

我会读取刚刚fgetc输入到文件中的数据

注意:我打开方式的变化

#include
int main()
{//打开文件FILE* pf = fopen("test.txt", "r");if (NULL == pf){perror("fopen");return 1;}//读文件int ch;while ((ch = fgetc(pf)) != EOF){printf("%c ", ch);}//关闭文件fclose(pf);pf = NULL;return 0;
}

fgetc读取了一个字符会自动向后移动一位

结果:

 fputs文本行输出函数

函数原型:

 返回:

代码:

一次输出一行

#include
int main()
{//打开文件FILE* pf = fopen("test.txt", "w");if (NULL == pf){perror("fopen");return 1;}//写文件fputs("hallo\n", pf);fputs("word", pf);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果:

 有此可见转意字符\n等也是可以操作的

补充:因为文件方式的原因会把之前的数据覆盖掉,成为新的数据如果想不覆盖要用追加的方式打开,我现在把打开方式改为追加执行

#include
int main()
{//打开文件FILE* pf = fopen("test.txt", "a");//注意我把打开方式改为了追加aif (NULL == pf){perror("fopen");return 1;}//写文件fputs("hallo\n", pf);fputs("word", pf);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果:

 还有一个二进制的追加ab,其余打开方式请自行去查看上面的表格

 fgets文本行输入函数

函数原型:

 返回:

代码:

一次输入一行

#include
int main()
{//打开文件FILE* pf = fopen("test.txt", "r");if (NULL == pf){perror("fopen");return 1;}//读文件char arr[] = "#######################";//用来观察一下的字符串fgets(arr, 20, pf);printf("%s", arr);//注意我这里没有加\n因为之前的输入里面是输入进去了\n的fgets(arr, 20, pf);printf("%s", arr);//关闭文件fclose(pf);pf = NULL;return 0;
}

注意我这里没有加\n因为之前的输入里面是输入进去了\n的

结果:

fprintf格式化输出函数

函数原型:

 可以发现只是多了一个参数其余并没有变化

返回:

代码:

格式化输出数据到文件中

#include
struct S
{char name[20];int age;float scores;
};int main()
{//打开文件struct S s = { "Laoli" ,20 ,95.5f };FILE* pf = fopen("test.txt", "w");if (NULL == pf){perror("fopen");return 1;}//写文件fprintf(pf, "%s %d %f\n", s.name, s.age, s.scores);//关闭文件fclose(pf);pf = NULL;return 0;
}

这个字符在输出字符串时遇到空格也会正常输出

结果:

fscanf格式化输入函数


函数原型: 

 返回:

代码:

把刚刚放进文件的数据格式化拿出来

#include
struct S
{char name[20];int age;float scores;};int main()
{//打开文件struct S s = { 0 };FILE* pf = fopen("test.txt", "r");if (NULL == pf){perror("fopen");return 1;}//读文件fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.scores));printf("%s %d %f", s.name, s.age, s.scores);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果:

这个函数在遇到空格会停止输入所有项,例如在Laoli中间加上空格:Lao li

fwrite二进制输出函数

函数原型: 

 

这个函数是以二进制的方式进行输出的

 返回:

 代码:

#include
struct S
{char name[20];int age;float scores;};int main()
{//打开文件struct S s = { "Laoli" ,20 ,95.5f };FILE* pf = fopen("test.txt", "wb");//注意我已经改变了文件的打卡方式if (NULL == pf){perror("fopen");return 1;}//写文件fwrite(&s, sizeof(struct S), 2, pf);//关闭文件fclose(pf);pf = NULL;return

注意我已经改变了文件的打卡方式

结果:

大家可以看到除了字符串什么都看不懂呀,这个烫烫烫烫烫烫是什么鬼呀,其实是因为二进制的形式存储的,计算机可以看懂就可以了,也可以利用fread函数查看内容

fread二进制输入函数

函数原型:

返回:

代码:

读取刚刚存入文件的数据,以二进制形式读取

#include
struct S
{char name[20];int age;float scores;};int main()
{//打开文件struct S s = { 0 };FILE* pf = fopen("test.txt", "rb");if (NULL == pf){perror("fopen");return 1;}//读文件fread(&s, sizeof(struct S), 1, pf);printf("%s %d %f", s.name, s.age, s.scores);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果:

 

四. 解析上述的流

以上函数都是在文件流中拿信息,是需要fopen函数来打开的文件流

还几个默认打开的流:

 代码:

 五.文件的随机读写

其实这些函数也并不是随机的,也是有规律的,但不再是从开头到结尾了

fseek

函数原型:

偏移量(字节为单位): 

向右移动用正数,向左移动用负数

 起始位置设置:

 返回:

代码:

我手动的在文件中添加这样的数据:

从末尾移动三位取出数据:

#includeint main()
{//打开文件FILE* pf = fopen("test.txt", "rb");if (NULL == pf){perror("fopen");return 1;}fseek(pf, -3, SEEK_END);int ch = fgetc(pf);printf("%c\n", ch);//关闭文件fclose(pf);pf = NULL;return 0;
}

 ftell

功能:返回文件指针相对于起始位置的偏移量

 函数原型:

返回: 

成功返回当前位置

 

 代码:

我们就用刚刚的代码加上函数试一下:

#includeint main()
{//打开文件FILE* pf = fopen("test.txt", "rb");if (NULL == pf){perror("fopen");return 1;}fseek(pf, -3, SEEK_END);int ch = fgetc(pf);printf("%c\n", ch);int pos = ftell(pf);printf("%d", pos);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果:

分析:

rewind

功能:让文件指针的位置回到文件的起始位置

函数原型: 

 

代码:

#includeint main()
{//打开文件FILE* pf = fopen("test.txt", "rb");if (NULL == pf){perror("fopen");return 1;}fseek(pf, -3, SEEK_END);int ch = fgetc(pf);printf("%c\n", ch);rewind(pf);//回到文件的起始位置int pos = ftell(pf);printf("%d", pos);//关闭文件fclose(pf);pf = NULL;return 0;
}

结果:

这个函数非常简单不做过多介绍了

 此片文章设计大量函数,记不住很正常,收藏一波需要的时候来查一查。

相关内容

热门资讯

简短七夕情人节祝福语 简短七夕情人节祝福语  无论是身处学校还是步入社会,大家都尝试过写祝福语吧,祝福语可以起到可以增进情...
创意教师节祝福语 2021创意教师节祝福语  在日常学习、工作或生活中,大家一定都接触过祝福语吧,祝福语可以起到可以增...
自己祝福自己母亲节祝福语 自己祝福自己母亲节祝福语(精选215句)  无论是在学校还是在社会中,大家或多或少都会用到过祝福语吧...
经典母亲节贺卡的祝福语 经典母亲节贺卡的祝福语  在日复一日的学习、工作或生活中,要用到祝福语的情况还是蛮多的,祝福语可以起...
送给朋友的祝福语 送给朋友的祝福语15篇  在现实生活或工作学习中,许多人都有过写祝福语的经历,对祝福语都不陌生吧,借...
暖心生日祝福语给老师 暖心生日祝福语给老师  无论在学习、工作或是生活中,许多人都有过写祝福语的经历,对祝福语都不陌生吧,...
聚会酒桌的祝福话 聚会酒桌的祝福话汇总  以真诚为半径,以尊敬为圆心,送你一个圆圆的祝福,给你端起这杯酒。以下是小编为...
升学宴祝福语 升学宴祝福语精选15篇  无论在学习、工作或是生活中,大家都写过祝福语,肯定对各类祝福语都很熟悉吧,...
春节喜庆的祝福语 春节喜庆的祝福语集合28句  每年的这个时候,祝福就像海洋涌向你,希望我的祝福像一叶轻舟,载你乘风破...
二十周年简短祝福语 二十周年简短祝福语  在日常学习、工作或生活中,大家都经常接触到祝福语吧,祝福语可以给人们带去温暖和...
表达元旦快乐的祝福语微信 精选表达元旦快乐的祝福语微信汇编30条  笑眼看星光璀璨,歌舞欢辞旧迎新,鞭炮响喜地欢天,巨龙飞五洲...
酒桌上的祝福话 酒桌上的祝福话(精选110句)  在日常的学习、工作、生活中,要用到祝福的话的情况还是蛮多的,祝福的...
升学宴的祝福语 升学宴的祝福语(精选145句)  在平日的学习、工作和生活里,要用到祝福语的情况还是蛮多的,祝福语可...
冬天祝福语 冬天祝福语(精选55句)  在平平淡淡的日常中,要用到祝福语的情况还是蛮多的,祝福语能给亲朋好带去好...
秋天祝福语 秋天祝福语(精选265句)  在我们平凡的日常里,说到祝福语,大家肯定都不陌生吧,祝福语是人们表达心...
世界教师日祝福语 世界教师日祝福语集锦  1、阳光普照,园丁心坎春意浓;甘雨滋润,桃李枝头蓓蕾红.——祝您教师节愉快!...
3.8妇女节祝福语微信摘录 3.8妇女节祝福语微信摘录56句  想送束花给你,却怕你误会我的意思;想写一首诗给你,却发现别人已经...
中秋节的优美祝福语 中秋节的优美祝福语(精选285句)  在日常学习、工作抑或是生活中,大家都不可避免地要接触到祝福语吧...