活动策划网站源码,做网站需要学会些什么,zoho企业邮箱,什么是单页面网站不知不觉我们已经学到C语言的文件操作部分了#xff0c;这部分内容其实很有意思#xff0c;因为它可以直接把我们代码中的数据写入硬盘#xff0c;而不是我们关掉这个程序#xff0c;代码就没有了#xff0c;让我们开始学习吧#xff01; 目录
1.为什么使用文件
2.什么…不知不觉我们已经学到C语言的文件操作部分了这部分内容其实很有意思因为它可以直接把我们代码中的数据写入硬盘而不是我们关掉这个程序代码就没有了让我们开始学习吧 目录
1.为什么使用文件
2.什么是文件
2.1程序文件
2.2数据文件
2.3文件名
3.文件的打开和关闭
3.1文件指针
3.2文件的打开和关闭
3.2.1fopen文件打开函数
3.2.2fclose关闭文件函数
3.2.3代码示例
3.2.4文件打开fopen模式
4.文件读写顺序
4.1文件的顺序读写
4.1.1fputc函数
4.1.2fgetc函数
代码示例
4.1.3fputs函数
4.1.4fgets函数
代码示例
4.1.5fprintf函数
4.1.6fscanf函数
代码示例
4.1.7fwrite函数
4.1.8fread函数
代码示例
4.2文件的随机读写
4.2.1fseek函数
4.2.2ftell函数
4.2.3rewind函数
代码示例
5.文本文件和二进制文件 1.为什么使用文件 1.使用文件我们可以将数据直接存放在电脑的硬盘上做到数据的持久化 数据存放在内存中 前面实现的通讯录当程序运行起来的时候可以给通讯录增加删除数据但是当程序退出的时候通讯录中的数据自然就不存在了当下次运行程序的时候数据又得重新录入这样的通讯录就很局限 数据存放在硬盘中 可以把数据记录下来只有我们自己选择删除数据的时候数据才会被销毁否则我们下次打开这个程序的时候上一次存入的数据都存在不会消失。下篇博客为大家实现 保持存入通讯录的数据一直存在这就涉及到我们数据持久化问题 2.我们一般把数据持久化的方法有 把数据存放在磁盘文件 把数据存放到数据库等方式 3.我们要学的是把数据放到磁盘文件中 2.什么是文件 简单来说磁盘上的文件就是文件就比如我们计算机上C盘中的文件夹下的文件 以上都是存放在硬盘中的文件 在程序设计中我们一般把文件分为两类从文件功能的角度分 程序文件 数据文件 我们主要学习数据文件 2.1程序文件 源程序文件后缀为.c 目标文件windows环境后缀为.obj 可执行程序Windows环境下后缀为.exe 2.2数据文件 文件的内容不一定是程序而是程序运行时读写的数据比如程序运行需要从中读取数据的文件或者输出内容的文件 数据在显示器上 处理数据的输入输出都是以终端为对象的就是从终端的键盘上输入数据运行结果显示到显示器上 数据在磁盘文件中 我们可以把信息输出到磁盘上当需要的时候再从磁盘上把数据读取到内存中使用 2.3文件名 我们都一个文件要有唯一的文件标识以方便用户的识别和引用 文件名包含三个部分文件路径文件名主干文件后缀 为了方便起见文件标识就被认为是文件名 3.文件的打开和关闭
3.1文件指针 1.什么是文件指针 在缓冲文件系统中关键的概念是“文件类型指针”简称“文件指针”每个被使用的文件都在内存中开辟了一个相应的文件信息区用来存放文件的相关信息例如文件名文件状态文件当前位置这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的取名FILE。 2.每当我们打开一个文件的时候系统会根据文件的情况自动创建一个FILE结构的变量并填充其中的信息使用者不必关心其中的细节一般都是通过FILE指针来维护这个FILE结构的变量这样使用起来更加方便 3.我们创建一个FTLE*的指针变量例如FILE* pf它就是一个文件指针变量 相信很多伙伴们又要问为什么要创建这个指针变量 指针pf是一个指向FILE类型数据的指针变量它就可以使pf指向某个文件的文件信息区通过该文件信息区中的信息就能够访问该文件也就是说通过文件指针变量能够找到与它相关联的文件 3.2文件的打开和关闭 我们都知道文件在读写之前应该先打开文件在使用结束之后关闭文件 在编写程序时再打开文件的同时都会返回一个FILE* 的指针变量来指向该文件这就相当于建立了指针和文件的关系 接下来让我们学习一下文件的打开fopen和关闭fclose这两个函数 3.2.1fopen文件打开函数 1.函数功能打开一个文件 2.头文件#includestdio.h 3.函数格式FILE *fopen( const char *filename, const char *mode ); filename文件名 mode文件打开方式下面会为大家总结一个表格 4.函数返回值 打开文件成功返回一个指向打开文件的指针 打开文件失败返回一个空指针 所以我们每次在打开文件的代码下要加一段代码来检测文件是否打开成功 3.2.2fclose关闭文件函数 1.函数功能关闭一个文件 2.头文件#includestdio.h 3.函数格式int fclose( FILE *stream ); stream流就是文件流 这里要为大家拓展关于“流”的知识 在我们C程序运行的时候默认打开三个流 stdin标准输入流就是我们在键盘上可以输入的数据 stdout标准输出流我们在屏幕上可以看到的数据 stderr标准错误流我们在屏幕上可以看到的数据 它们的类型都是FILE* 所以我们在写C程序的时候才不需要在打开流因为它是默认打开这三个流的 在进行文件操作的时候我们是没有默认打开流的这时需要我们手动给它添加一个流 然后进行读取写入等操作 我们这里的 FILE *stream 就是一个文件流 例如FILE* pf“test.txt”,w;这个语句里pf这个文件指针就是一个文件流 那么我们为什么要有流呢我们的数据是不能直接传输到输出设备上的它是通过流进行传输的目前我们知道这些进行文件操作的时候就不会觉得难以理解了。 4.函数返回值 文件关闭失败函数返回值是0同时需要我们把文件指针置为NULL 文件关闭失败函数返回EOF来指示错误 3.2.3代码示例 现在介绍完fopen和fclose函数了让我们看个代码来进一步理解这两个函数的使用 #define _CRT_SECURE_NO_WARNINGS 1
#includestdio.h
#includestdlib.h
#includeerrno.hint main()
{//打开一个文件以只读的模式打开FILE* pf fopen(test.txt, r);//这里的文件名如果我们想要使用//已经存在也就是创建好的文件我们需要把文件路径给完整的加上//检测文件是否打开成功成功则进入文件失败返回空指针if (pf NULL){perror(fopen);return 1;}//进入文件进行读文件//...//关闭文件fclose(pf);pf NULL;return 0;
} 我们运行代码发现显示了错误信息 提醒我们没有这个文件这就引出了我们下一个知识点文件打开模式有哪些以只读模式打开文件为什么会打开失败。 3.2.4文件打开fopen模式 这里给大家总结了一个表格我们可以对照表格选择我们需要的文件打开模式 这里我们要注意以写的形式打开一个文件时上次书写在文件中的数据将会被销毁这次打开文件输入的内容将覆盖上一次的内容 4.文件读写顺序 文件读写分为顺序读写和随机读写两类 我们在学习这部分内容之前还需要明确一个知识点 在我们平时写C语言时是面向程序的数据显示到屏幕上 今天学习的面向文件操作数据显示到文件中 知道输入和输出的面向关系我们才能更好的学习这部分知识 4.1文件的顺序读写 文件的顺序读写就是按顺序读写一个诶一个 这里我们学习几个函数来帮助我们更好的认识文件顺序读写 字符输入输出函数fgetc/fputc 文本行输入输出函数fgets/fputs 格式化输入输出函数fscanf/fprintf 二进制输入输出函数fread/fwrite 前三对函数适用于所有流既适用于标准输出流也适用于文件流 最后一对仅适用于文件流 我们一对一对来介绍 4.1.1fputc函数 1.函数功能将字符写入文件流或者标准输出流 2.头文件#includestdio.h 3.函数格式int fputc( int c, FILE *stream ); 这里的c要输出写入的字符 代码示例我们与fgetc函数放在一起实现 4.1.2fgetc函数 1.函数功能从文件流或者标准输入流中读取字符 2.头文件#includestdio.h 3.函数格式int fgetc( FILE *stream ); 4.函数返回值 读取成功返回作为int读取的字符 读取失败返回EOF以指示错误或文件结束 下面我们来看个代码理解这两个函数 代码示例 int main()
{//打开一个文件FILE* pf fopen(test1.txt, w);//以写的形式打开//判断文件是否打开成功if (pf NULL){perror(fopen);return 1;}//文件打开成功进行写文件fputcchar ch 0;for (ch a; ch z; ch){fputc(ch, pf);}//书写完毕关闭文件fclose(pf);pf NULL;//打开这个文件我们进行读取操作FILE* ptf fopen(test1.txt, r);//以读的形式打开if (ptf NULL){perror(fopen);return 1;}//开始读取,我们读取四次int tmp fgetc(ptf);printf(%c\n, tmp);tmp fgetc(ptf);printf(%c\n, tmp);tmp fgetc(ptf);printf(%c\n, tmp);tmp fgetc(ptf);printf(%c\n, tmp);//读取完毕关闭文件fclose(ptf);ptf NULL;return 0;
} 打开文件所在文件夹我们可以看到文件中已经存入数据这是fputc函数的功能在文件中写入了数据 运行代码我们可以看到屏幕上的结果读取到了a b c d 这是fgetc函数的功能 4.1.3fputs函数 1.函数功能将字符串写入文件流或者标准输出流 2.头文件#includestdio.h 3.函数格式int fputs( const char *string, FILE *stream ); string我们需要写入的字符串 4.函数一次性只能写入一条字符串 代码示例我们与fgets函数放在一起实现 4.1.4fgets函数 1.函数功能从文件流或者标准输入流中读取字符串 2.头文件#includestdio.h 3.函数格式char *fgets( char *string, int n, FILE *stream ); string数据存储的位置通俗来说就是从stream中要读的字符串放到string中 n要读取的最大字符数 4.函数返回值 读取成功返回该条字符串 读取失败返回一个空指针NULL 5.函数一次性只能读取一条字符串 我们来看段代码加深理解 代码示例 int main()
{//打开一个文件FILE* pf fopen(test1.txt, w);//以写的形式打开//判断文件是否打开成功if (pf NULL){perror(fopen);return 1;}//文件打开成功进行写文件fputcfputs(hello world!\n, pf);fputs(亚里士多德!\n, pf);fputs(hehe\n, pf);//书写完毕关闭文件fclose(pf);pf NULL;//打开这个文件我们进行读取操作FILE* ptf fopen(test1.txt, r);//以读的形式打开if (ptf NULL){perror(fopen);return 1;}//开始读取char buf[30] { 0 };fgets(buf, 5, ptf);//读取完毕关闭文件fclose(ptf);ptf NULL;return 0;
} 我们打开文件可以看到文件中已经写入fputs三行数据 我们运行代码读取fgets第一行的数据 我们预想中的hello并没有出现而是hell这是因为要留一个字符位置来存放‘\0’如果想要打印hello要让n6 4.1.5fprintf函数 1.函数功能格式化把数据写入文件流或者标准输出流 2.头文件#includestdio.h 3.函数格式int fprintf( FILE *stream, const char *format [, argument ]...); char *format格式化控制字符串就是说它以什么形式输出例如%d %s %f [argument ]...可选参数就是对应形式的打印参数是什么 4.函数返回值 写入成功返回写入的字节数 写入失败函数中的每一个都会返回一个负值 代码示例我们与fscanf函数放在一起实现 4.1.6fscanf函数 1.函数功能从文件流或者标准输入流中读取格式化数据 2.头文件#includestdio.h 3.函数格式int fscanf( FILE *stream, const char *format [, argument ]... ); char *format 格式化控制字符串就是说它以什么形式输入例如%d %s %f [argument ]...可选参数就是对应形式的打印参数是什么 4.函数返回值 读取成功返回成功转换和分配的字段数 读取失败发生错误或者在第一次转换之前到达文件流的末尾的情况下则返回值为fscanf的EOF 返回值0表示未分配任何字段 我们来看段代码进一步了解 代码示例 struct S
{char name[12];int age;float score;
};
int main()
{//打开一个文件struct S s1 { 张翰,34,94.3 };FILE* pf fopen(test1.txt, w);//以写的形式打开//判断文件是否打开成功if (pf NULL){perror(fopen);return 1;}//文件打开成功进行写文件fprintffprintf(pf, %s %d %f, s1.name, s1.age, s1.score);//书写完毕关闭文件fclose(pf);pf NULL;//打开这个文件我们进行读取操作FILE* ptf fopen(test1.txt, r);//以读的形式打开if (ptf NULL){perror(fopen);return 1;}//开始读取struct S s2 { 0 };fscanf(ptf, %s %d %f, s2.name, (s2.age), (s2.score));printf(%s %d %f\n, s2.name, s2.age, s2.score);//读取完毕关闭文件fclose(ptf);pf NULL;return 0;
} 我们这里的结构体中存放的就是格式化的数据 打开文件发现文件中已经写入fprintf数据 运行代码读取fscanf屏幕上显示文件中的数据 4.1.7fwrite函数 1.函数功能以二进制输出数据将数据写入文件流 2.头文件#includestdio.h 3.函数格式size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream ); void *buffer指向要写入的数据的指针 size要写的元素的大小即每个元素所占字节的大小 count最多写入几个元素 FILE *stream文件流 4.函数返回值 写入成功写入的完整项目数即count 写入失败该数字可能小于count此外如果发生错误则无法确定文件位置指示器 代码示例我们与fread函数放在一起实现 4.1.8fread函数 1.函数功能以二进制输入数据从文件中读取数据 2.头文件#includestdio.h 3.函数格式size_t fread( void *buffer, size_t size, size_t count, FILE *stream ); buffer数据存储位置 size要读的元素的大小即每个元素所占字节的大小 count最多读取几个元素 4.函数返回值 读取成功返回实际读取的完整项目数即count如果发生错误或在达到count之前遇到文件末尾则该数字可能小于count 读取失败使用feof或ferror函数来区分读取错误和文件结束条件。如果大小或计数为0则fread返回0并且缓冲区内容不变。 接下来我们看段代码来加深了解 代码示例 //fwrite fread
struct S
{char name[12];int age;float score;
};
int main()
{//打开一个文件struct S s1 { 张翰,34,94.3 };struct S s3 { 黄晓明,55,88.9 };FILE* pf fopen(test1.txt, wb);//以二进制写的形式打开//判断文件是否打开成功if (pf NULL){perror(fopen);return 1;}//文件打开成功进行写文件fwrite(s1, sizeof(s1), 1, pf);fwrite(s3, sizeof(s3), 1, pf);//书写完毕关闭文件fclose(pf);pf NULL;//打开这个文件我们进行读取操作FILE* ptf fopen(test1.txt, rb);//以二进制形式打开要读的文件if (ptf NULL){perror(fopen);return 1;}//开始读取struct S s2 { 0 };fread(s2, sizeof(s2),1,ptf);printf(%s %d %f\n, s2.name, s2.age, s2.score);fread(s2, sizeof(s2), 1, ptf);printf(%s %d %f\n, s2.name, s2.age, s2.score);//读取完毕关闭文件fclose(ptf);pf NULL;return 0;
} 打开文件我们发现文件中已经被写入fwrite二进制数据我们是看不懂的 我们发现只有汉字我们可以看懂这是因为汉字的二进制形式与汉字本身形式相同 运行代码我们读取fread数据到屏幕上屏幕上显示数据读取成功 4.2文件的随机读写 文件顺序读写有对应的函数同样文件的随机读写也有对应的函数我们在这里介绍3个对应函数fseek ftell rewind 我们继续往下了解 4.2.1fseek函数 1.函数功能将文件指针移动到指定位置 2.头文件#includestdio.h 3.函数格式int fseek( FILE *stream, long offset, int origin ); offect偏移量也就是当前指针位置到目标位置的字节数 指针从左—右偏移量为正数 指针从右—左偏移量为负数 origin起始位置它还被定义了三个量 SEEK_SET文件其实位置 SEEK_CUR文件当前指针位置 SEEK_END文件末尾 4.函数返回值 读取成功fseek将返回0 读取失败它将返回一个非零值在无法查找的设备上返回值未定义 我们将代码例子与ftell函数和rewind函数放在一起 4.2.2ftell函数 1.函数功能获取文件指针的当前位置通俗来说这个函数就是让我们来求偏移量的也就是文件指针相较于起始位置的偏移量 2.头文件#includestdio.h 3.函数格式long int ftell( FILE *stream ); 4.函数返回值 读取成功返回文件指针相较于起始位置的偏移量 读取失败ftell返回–1L偏移量errno设置为errno.H中定义的两个常量之一 我们和rewind函数一起来 看代码例子 4.2.3rewind函数 1.函数功能将文件指针重新定位到文件起始位置 2.头文件#includestdio.h 3.函数格式void rewind( FILE *stream ); 我们来看个代码进一步加深理解这两个函数 代码示例 int main()
{FILE* pf fopen(test2.txt, w);if (pf NULL){perror(fopen);return 1;}//在文件中写入abcdefgchar ch 0;for (ch a; ch z; ch){fputc(ch, pf);}//写入完成关闭文件fclose(pf);pf NULL;//再次打开文件进行随机读取文件FILE* ptf fopen(test2.txt, r);if (ptf NULL){perror(fopen);return 1;}//先按顺序往下读3个字符char tmp fgetc(ptf);//aprintf(%c\n, tmp);tmp fgetc(ptf);//bprintf(%c\n, tmp);tmp fgetc(ptf);//cprintf(%c\n, tmp);//读取完三次后我们想再次读取b而不是按顺序读取到d此时//我们需要使用fseek函数fseek(ptf, -2, SEEK_CUR);//改变指针位置tmp fgetc(ptf);printf(%c\n, tmp);//此时读取到b//假设在此时我们不知道文件指针的当前位置这时我们就需要用到// ftell函数来求一下当前文件指针的偏移量printf(文件指针相较于起始位置的偏移量是%d\n, ftell(ptf));//得到这个文件指针偏移量后我们想把文件指针归到文件起始位置// 这时需要用到我们的rewind函数rewind(ptf);//我们打印一个字符验证一下查看是否文件指针回到了文件起始位置如果// 回到了则打印出来的是a//进行读取字符tmp fgetc(ptf);printf(是起始字符;%c \n, tmp);//读取完毕关闭文件fclose(ptf);ptf NULL;return 0;
}int main()
{FILE* pf fopen(test2.txt, w);if (pf NULL){perror(fopen);return 1;}//在文件中写入abcdefgchar ch 0;for (ch a; ch z; ch){fputc(ch, pf);}//写入完成关闭文件fclose(pf);pf NULL;//再次打开文件进行随机读取文件FILE* ptf fopen(test2.txt, r);if (ptf NULL){perror(fopen);return 1;}//先按顺序往下读3个字符char tmp fgetc(ptf);//aprintf(%c\n, tmp);tmp fgetc(ptf);//bprintf(%c\n, tmp);tmp fgetc(ptf);//cprintf(%c\n, tmp);//读取完三次后我们想再次读取b而不是按顺序读取到d此时//我们需要使用fseek函数fseek(ptf, -2, SEEK_CUR);//改变指针位置tmp fgetc(ptf);printf(%c\n, tmp);//此时读取到b//假设在此时我们不知道文件指针的当前位置这时我们就需要用到// ftell函数来求一下当前文件指针的偏移量printf(文件指针相较于起始位置的偏移量是%d\n, ftell(ptf));//得到这个文件指针偏移量后我们想把文件指针归到文件起始位置// 这时需要用到我们的rewind函数rewind(ptf);//我们打印一个字符验证一下查看是否文件指针回到了文件起始位置如果// 回到了则打印出来的是a//进行读取字符tmp fgetc(ptf);printf(是起始字符;%c \n, tmp);//读取完毕关闭文件fclose(ptf);ptf NULL;return 0;
} 运行结果 在这里我们要特别说明一下那个文件光标位置 打开我们写入的文件我们发现光标在文件起始位置这是因为文件指针默认指向第一个字符当我们一次往后读取fgetc字符时文件指针会自增1会直接往下走而不是一直打印那一个字符这个不需要我们程序员来操作。 5.文本文件和二进制文件 什么是文本文件什么又是二进制文件 1.根据数据的组织形式数据文件被称为文本文件或者二进制文件 2.数据在内存中以二进制的形式存储如果不加转换的输出到外存就是二进制文件 ps这种二进制文件我们一般是看不懂的看不懂思密达 3.如果要求在外存上以ASCII码的形式存储则需要在存储前转换以ASCII码字符的形式存储的文件就是文本文件 ps看得懂思密达 我们举个简单的例子来看什么是二进制存储什么是ASCII存储 例如我们要把整数10000存入内存中 它在内存中原来就是以二进制的补码形式存储的也就是 00000000 00000000 00100111 00010000 不清楚源码反码补码关系的伙伴可以去我这篇博客中了解源码反码补码的关系 以文本文件ASCII形式存储 这是整数10000它的五个位数一次转换为ASCII对应值也就是 以二进制的形式存储 就是不加转换的二进制码00000000 00000000 00100111 00010000 它在文件中显示出来的数据我们是看不懂的 可以举个代码例子 int main()
{//以二进制的形式进行写入FILE* pf fopen(test3.txt, wb);if (pf NULL){perror(fopen);return 1;}int a 10000;fwrite(a, 4, 1, pf);fclose(pf);pf NULL;//以二进制的形式进行读取FILE* ptf fopen(test3.txt, rb);if (ptf NULL){perror(ptf::fopen);return 1;}int b 0;fread(b, 4, 1, ptf);printf(%d \n, b);fclose(ptf);ptf NULL;return 0;
} 我们打开对应的文件可以看到里面存储的数据 由于这篇博客字数已经到极限了我们还剩下一点内容文件读取结束的判定和文件缓冲区我们放到下一篇博客好了大家下期再见