目录
前言
文件的概述
文件类型
如何用C语言来操作文件呢?
文件缓冲区
文件的打开与关闭
文件的打开——fopen()函数
文件的关闭——fclose()函数
文件结束检测——feof()函数
文件的顺序读写
文件字符输出函数——fputc()
文件字符输入函数——fgetc()
文件字符串输出函数——fputs()
文件字符串输入函数——fgets()
格式化输出——fprintf()
格式化输入——fscanf()
文件的随机读写
取文件位置指针的当前值——ftenll()函数
移动文件位置指针——fseek()函数
置文件指针于文件的开头——rewind()函数
综合应用——将一个文件的内容拷贝到另一个文件
总结
前言
计算机的内存中运行的程序和数据在关机后会自动消失。我们可以看看下面这种情况
我们可以看到,我们给a赋值一个3,然后再屏幕上打印出它的值,但是,当我们关闭这个程序时,在下一次打开程序时,它还会提醒我们输入一个值,但这次的值就不一定是3了,它没有保存下来。所以说我们就需要学习文件的相关知识,将我们写的程序内容能够保存下来。操作系统提供了对数据进行统一组织和管理的功能,就是以“文件”的形式把数据储存在计算机的存储介质上。
文件的概述
一个文件是由一系列彼此有一定联系的数据集合构成的。就像是我们把社会上的一个个家庭作为社会的基本组成单位一样,也可以把家庭中的每一个成员看作是一个数据,并且通常以户主名来标识不同的家庭。同样,为了区分不同类型的数据构成的不同文件,我们给每一个文件取一个名字,就是文件名,我们在使用电脑的时候,肯定发现过一些 带有 . exe或者 . c等等的文件后缀名,这就是对文件进行了一个简单的分类,比如我们写C语言的时候,我们写的源文件通常都会放在同一个相同的文件夹中,这样方便我们日后查找修改等操作。
文件类型
C语言中文件按其储存数据的格式可分为文本文件和二进制文件。那么文本文件和二进制文件有什么不同呢。
首先,从概念上讲,文本文件中的数据都是以单个字符的形式进行存放的,每个字节储存的是一个字符的ASCII码值,把一批彼此相关的数据以字符的形式存放在一起构成的文件就是文本文件(也叫ASCII码文件)。而二进制文件中的数据顾名思义就是以二进制的方式储存的。数据在内存中就是以二进制的方式储存的,也就是说数据原本在内存中是什么样子的,在二进制文本中就是什么样子的。
我们举个例子来看看,两个文件的明显区别。就拿一个整数12345来说,在文本文件中,就是以字符‘1’ ‘2’ ‘3’ ‘4’ ‘5’的方式来储存的,每个字节都是放的他们的ASCII码值,所以5个字符就占据5个字节的空间,而对于二进制储存来说12345,就是一个整形变量,是一个int(4个字节)的大小。我们画图来表示一下。
在文本文件中的储存形式:
在二进制文件中的储存形式:
00110001 00110010 00110011 00110100 00110101
00110000 00111001 综上,文本文件和二进制文件有以下区别:
1.由于储存的数据不同,所以在进行读写操作时,文本文件是以字节为单位进行写入或读出的;而二进制文件则以变量,结构体等数据块为单位进行读写。
2.一般来讲,文本文件用于储存文字信息,一般由可显示字符构成,如说明性文档,C语言的源程序文件等都是文本文件;二进制文件用于储存非文本数据。
具体应用时,应根据我们自身的需要来选择。
如何用C语言来操作文件呢?
在C语言中,所有对文件的操作都是通过文件指针来完成的。我们已经学习过指针了,变量的指针指向该变量的储存空间;但文件的指针不是指向一段内存空间,而是指向关于该文件的一个结构体,该结构体定义在<stdio.h>中。
声明一个文件指针的语法格式如下:
FILE* 文件指针名;
注意:FILE 必须全是大写字母,另外一定要包含<stdio.h>的头文件
文件缓冲区
文件缓冲区可以理解成用来积累数据的,当数据积累到一定量的时候,然后再进行读取数据,当该缓冲区的数据被读完时,将再从输入文件中输入一批新的数据放进去。这里我们就了解一下这个缓冲区就行。
文件的打开与关闭
文件的打开——fopen()函数
在C语言中,打开文件就是把程序中要读,写的文件与磁盘上实际的数据文件联系起来,让文件指针指向该文件,用于进行相应的操作。C语言中输入/输出函数库中定义的打开文件的函数是fopen()函数。其使用格式如下:
FILE *fp ; //首先声明一个文件指针
fp=fopen("文件名","打开方式") //根据打开方式的不同,对文件的操作就不同。
如果文件打开成功,fopen()函数则返回一个FILE型的指针;若打开失败则返回一个空指针。所以当我们打开文件的时候,需要判断文件是否打开成功了。可以用一个if语句来判断。
注意:fopen的两个参数都需要用双引号括起来
有关的打开方式及其含义都在上面图中,可以参考。
提示:只读方式表示只对文件读取内容,不能进行写的操作;只写表示对文件只能进行写入操作,不能进行读的操作;追加表示在文件末尾进行添加数据的操作;读写操作表示既可以读内容也可以写内容;而建立新文件表示如果原文件存在,则覆盖原文件。
不管是对文件进行任何操作,都需要判断文件是否被打开。所以在进行打开文件的操作的时候,都要检查操作是否成功。通常像这样检查:
FILE* fp = fopen("abc.txt", "r"); if (fp == NULL) {perror(fp);exit(1); }
我们可以使用一个if语句来判断。打开成功,则再进行一系列的读写操作,打开失败,则跳出程序。
文件的关闭——fclose()函数
我们既然把文件打开了,则肯定需要文件关闭,意思就是将我们打开文件的指针给收回。我们只需要调用一下fclose()即可。
fclose(fp); //fp就是我们上面打开过的指针。
技巧:因为保持一个文件的打开状态需要占用内存空间,所以对文件的操作一般遵循“晚打开,早关闭”的原则,避免浪费。
文件结束检测——feof()函数
该函数是用于检测文件是否结束,既适用于二进制文件,也适用于文本文件。其使用格式如下。
feof(fp); //fp是文件指针,是已经打开文件的指针
作用:测试文件指针fp是否指向文件的尾部。若已经读到尾部,则返回0;否则,返回0;
在进行读的操作的时候,需要检测是否读到文件尾部,就可以使用"while(!feof(fp))"循环语句来控制对文件内容的读取。如果不是文件尾部,则括号里的值为1,继续读取并循环,直到文件的末尾结束。
例如:
while (!feof(fp)) {c = getc(fp); //从文件中读取一个字符赋给c }
文件的顺序读写
我们已经将文件的基本内容(文件的打开关闭等操作)讲完了,现在我们就开始读写文件了,并练习使用一些关于操作文件的读写函数。
文件的顺序读写常用的函数如下。
字符输入/输出函数:fgetc(),fputc()
字符串输入/输出函数: fgets(),fputs()
格式化输入/输出函数:fscanf(),fprintf()
数据块输入/输出函数:fread(),fwrite()
以上函数都包含在头文件stdio.h中,因此在调用以上函数时,要包含头文件。
在进行文件读写时我们需要创建文件。
我们通过上面的操作打开一个文件,并给它取名为“data.txt.txt”,打开完后,我们可以把他也显示在VS中,现在我们可以开始写的操作了。
文件字符输出函数——fputc()
int main() { //我们先打开文件FILE*fp= fopen("data.txt.txt", "w");//判断是否为空指针,是空指针提前退出if (fp == NULL){perror(fp);return 0;}//定义一个字符变量char tmp= 'a';//将该变量写入到文件中fputc(tmp, fp);//关闭文件fclose(fp);//将fp变为空,避免变为野指针fp = NULL;return 0; }
当我们看到终端什么都没显示时,表示已经写入成功,我们点入“data.txt.txt”中,发现已经写入成功。
这个时候我们,再将该字符拿出来。
文件字符输入函数——fgetc()
我们有时候分不清fgetc和fputc两个的区别,就看它们的形参就行了,fgetc形参要少一个,fputc的形参要多一个,它需要加上我们要输入到文件的字符,而fgetc只需要从文件中拿一个字符出来,就只有指针变量。接下来我们用fgetc从文件中再把这个字符拿出来。
int main() { //我们先打开文件FILE*fp= fopen("data.txt.txt", "r");//判断是否为空指针,是空指针提前退出if (fp == NULL){perror(fp);return 0;}//定义一个字符变量char tmp;//将该变量写入到文件中tmp=fgetc(fp);printf("%c", tmp);//关闭文件fclose(fp);//将fp变为空,避免变为野指针fp = NULL;retu
在代码上我们的打开文件的方式已经改变,改为了"r"读的方式,一定要注意,当我们在代码中想要打印字符tmp,可以看到还是那个字符。当然我们也可以连续的读取。我们只需要写一个循环即可。
文件字符串输出函数——fputs()
fputs是将一个存放在内存变量中的字符串写到文本文件中,使用格式如下:
fputs(字符串,文件指针);
下面我们还是上代码。
int main() {//我们先打开文件FILE* fp = fopen("data.txt.txt", "w");//判断是否为空指针,是空指针提前退出if (fp == NULL){perror(fp);return 0;}char arr[] = { "man whta can i say mamba out" };fputs(arr, fp);fclose(fp);fp = NULL;return 0; }
可以看到,文件中就是我们想输入进去的代码。我们要时刻注意打开文件的方式,在我写这个代码的时候就忘了改方式,第一次就没有写入成功。
好,下面我们再尝试从改文件将这个字符串拿出来。
文件字符串输入函数——fgets()
fgets()函数是从文本中读取一个字符串,保存在变量中。使用格式如下:
fgets(字符串指针,读取字符个数n,文件指针);
当我们使用的时候,要注明我们要读取字符的个数,但是它只会读取n-1个,因为字符串最后一个字符必须是‘\0’,系统会默认给末尾加上‘\0’,所以说我们读取的时候总比我们想要读取的少一个。
int main() {//我们先打开文件FILE* fp = fopen("data.txt.txt", "r");//判断是否为空指针,是空指针提前退出if (fp == NULL){perror(fp);return 0;}char arr[50];fgets(arr,20, fp);fclose(fp);printf("%s\n", arr);fp = NULL;return 0; }
当满足下列调钱之一时,读取过程结束。
1.已读取了n-1个字符。
2.当前读取的字符是回车符。
3.已读到文件末尾。
格式化输出——fprintf()
有的时候我们对要输入/输出的数据有一定的格式要求,如整形,字符型或按指定的宽度输出数据等。这里要介绍的格式化输入/输出指的是不仅输入/输出数据,还要指定输入/输出数据的格式,它比前面介绍字符/字符串输入/输出函数的功能更加强大。
fprintf()与前面我们学过的printf()函数相似,只是将输出的内容放在一个指定的文件中。使用格式如下:fprinf(文件指针,格式串,输出列表);执行成功时,返回输入的字节数,否则返回一个负数。
int main() {//我们先打开文件FILE* fp = fopen("data.txt.txt", "w");//判断是否为空指针,是空指针提前退出if (fp == NULL){perror(fp);return 0;}char tmp[] = "hello world";fprintf(fp, "%s", tmp);fclose(fp);fp = NULL;return 0; }
同样的是写入成功了。
当然我们如果像要读取文件的话,也是同样的操作。
格式化输入——fscanf()
fscanf()函数与scanf函数的使用方法差不多,只需要加入一个指针就行了,使用格式如下:
fscanf(文件指针,格式串,输入列表);这里我们就不使用代码演示了,大家可以自己试一下,和前面的方法都差不多。
关于二进制的读写这里就不说了,我们相对用得比较少。
文件的随机读写
相对于前面介绍的顺序访问文件方式,文件的随机访问是给定文件当前读写位置的一种读写文件方式,也就是允许对文件进行跳跃式的读写操作。
要定位文件的当前读写位置,这里要提到一个文件位置指针的概念。所谓文件位置指针,就是值当前读或写的数据在文件中的位置,在实际使用中,是由文件指针充当的。当进行文件读操作时,总是从文件位置指针开始读其后的数据,然后位置指针到尚未读的数据之前;当进行写操作时,总是从文件指针开始去写,然后移到刚写入的数据之后。下面我们介绍文件位置指针的定位函数。
取文件位置指针的当前值——ftenll()函数
ftell函数用于获取当前文件指针距离文件开始的位置。返回文件指针相对于文件开头的位移量,单位是字节。调用失败则返回-1。
移动文件位置指针——fseek()函数
fseek()函数用来移动文件指针到指定位置上,然后从该指针位置进行读写操作,从而实现对文件的随机读写功能。使用格式如下:
fseek(fp,offset,from);
其中fp是文件指针;offset是文件位置指针的位移量,是一个long型的数据。若位移量为正,则前进,位移量为负,则反向移动。from是起始点,用以指定位移是以哪个位置为基准的。
上表给出了代表起始点的符号常量和数字及其含义,在fseek函数中使用时两者是等价的。
例如:
fseek(fp,100L,0); //从文件开头向后移动100个字节
fseek(fp,50L,1); //从文件指针当前位置向后移动50个字节
fseek(fp,-30,2); //从文件结尾向前移动30个字节
置文件指针于文件的开头——rewind()函数
rewind()函数用于将文件指针的位置置于文件的开头。其形式如下:
rewind(fp);综合应用——将一个文件的内容拷贝到另一个文件
我们已经学习了上面的关于文件操作的函数了,下面我们就用他们来解决一下上面这个问题。将文件内容拷贝到另一个文件。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { char arr[256];int ch=0;//以读的形式打开文件,并将他赋给指针sorceFILE* sorce = fopen("data.txt.txt", "r");//判断该指针if (sorce == NULL){perror(sorce);}//以写的形式打开文件,我们要向里面写入数据FILE* dest = fopen("ffff.txt", "w");//判断该指针if (dest == NULL){perror(dest);}//我们先从sorce中读取256个字符到数组arr中fgets(arr,256, sorce);//我们再从将得到的字符串写入dest中fputs(arr, dest);//最后关闭两个文件fclose(sorce);fclose(dest);sorce = NULL;dest=NULL;return 0; }
我们可以看到开始的时候两个文件中的内容是不相同的,
当我们运行了程序之后,两个文件中的内容都相同了,其实我们也可以用fprintf和fscanf函数来完成上面这些操作,只不过我们这里用的是fputs和fgets。其实当你练习时,可以尝试用用其他两个函数。
本书很多内容都参考了书籍《C语言从入门到精通》的文件部分内容。
总结
以上就是关于文件的一些函数知识的讲解和应用,希望对大家的C语言学习有所帮助,码了3个多小时,希望大家能够点赞,关注,收藏起来,以后再看看,感谢大家的观看!