文件操作(C/C++)

        本篇将较为详细的介绍在C/C++中的一些文件操作。其中首先介绍了上面时文件,然后就是在文件中比较抽象的概念:流,然后就是文件指针与文件的读和写,接着就是顺序读写、随机读写,还有文件读取结束时的判定。

1.什么是文件?

        磁盘上的文件就被称为文件,这仅仅只是文件的一个简单定义,下面将细分文件的定义。

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

        数据文件:文件的内容不仅仅只会有程序文件还有程序运行时读写的数据,即从文件中读出数据或者在文件中写入数据。

        在数据文件的细分下,还分为:二进制文件和文本文件。

        二进制文件:数据在内存中以0/1二进制的存储方式的存储,并且不加转化的存储到外村。

        文本文件:在存储到外存前将数据二进制转化为ASCII码的形式存储起来。

        对于二进制文件和文本文件的理解可如下图:

文件操作(C/C++)_第1张图片

        将10000每一个数字都转化为对应的ASCII码形式的存储即就是为文本文件存储方式,10000转化为对应的二进制序列就是二进制的文件存储。 

2.流和标准流

        :在程序中,我们需要将数据输出到各种各样的外部设备中,同时也需要从外部设备中读取数据,但是在不同的外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行操作,抽象出了流的概念,如下图:

文件操作(C/C++)_第2张图片

        这就是将数据给输入输出的操作给抽象出来,不用管在不同的设备间数据的输入和输出。

         标准流:在C语言中,当程序启动时,便自动打开了3个流:

         stdin - 标准输入流:在大多数的环境中从键盘输入,scanf函数就是从标准输入流中读取数据。

         stdout - 标准输出流:大多数的环境中,输出至显示器界面,printf函数就是将信息输出到标准输出流中。

        stderr - 标准错误流:大多数环境中输出到显示器界面。

        对于以上的三个标准流的类型为:FILE*,被称为文件指针。在C语言中,就是通过文件指针来维护流的各种操作的。

3.文件指针

        对于每一个文件都会在内存中开辟一个相对应的文件信息区,用来存放文件信息区的相关信息。这些信息是存储在结构体变量中的,该结构体类型由系统声明,取名为FILE。文件指针即为FILE*。

        每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构体的变量,并且填充其中的信息,如何通过一个FILE* 的变量来维护该信息区,如下图:

文件操作(C/C++)_第3张图片

        当文件Data.txt被打开时,系统自动会创建一个文件信息区 f (为FILE类型),然后通过 pf (FILE*类型)来对该文件信息区进行维护,其中圈住的就可以理解为流,我们并不需要关注这一步。

4.文件的打开与关闭

        文件的打开与关闭同样涉及文件指针FILE*,对于文件的打开需要使用以下的库函数以及对应的格式:

文件操作(C/C++)_第4张图片

        对于该函数,其中涉及的第一个参数为文件名,第二个参数即为对应的打开方式,对于第二个参数的参数,在以下列举:

文件操作(C/C++)_第5张图片

        以上便是对于fopen函数中第二个参数对应的可选变量(还包括一些其他的可选变量,不过这些是用得比较多的),以下将给出对于fopen函数的使用举例。 

文件操作(C/C++)_第6张图片

        如上图所示,当运行该代码的时候,已经在对应的文件夹位置创建了一个对应的文件,对于其他的一些我就不在一一列举,对于fclose函数的使用如上图所示,将文件指针传入fclose中即可,即代表关闭了文件,用法类似于free函数

        但是需要注意的是,如果我们的文件原本含有数据,用以上的只写“w”来打开文件,会导致文件中的内容被清空,所以我们在选用打开文件的时候,是需要选择合适的打开方式的。

        还有就是对于文件的创建位置,我们用一个 .  表示当前路径,两个 .. 表示上一级路径,当我们在fopen参数对应的第一个参数按照以上的方式,即可在对应的位置创建文件,如下:

文件操作(C/C++)_第7张图片

         如上,在当前路径的上一路径创建文件,创建成功。这种方法为当前路径创建法,还有另一种方法为绝对路径创建法,如下:

文件操作(C/C++)_第8张图片

        不过通常我们使用的创建方法都是第一种,直接输出文件名。 

5.文件的顺序读写

        对于文件的顺序读写,即就是按照顺序写入文件中,或者从中读出数据。

5.1 fgetc和fputc函数

        对于fgetc和fputc函数都适用于所有流,fgetc为字符输入函数,适用于所有输入流(stdin,文件……),fputc为字符输出函数,适用于所有输出流(stdout、文件……)。

        对于fputc函数的使用:

文件操作(C/C++)_第9张图片

        其中传入的第一个参数为int类型,即传入字符的ASCII码,第二个为流,即文件指针。具体操纵如下:

文件操作(C/C++)_第10张图片

        如上图所示,运用一个for循环,成功将26个小写字母写入到了文件中,接下来关于fgetc的函数使用,如下:

        如上的参数,我们只需要将文件指针传入fgetc,返回值的类型为int型,如果读取失败,那么返回的值为EOF,使用方法如下:

文件操作(C/C++)_第11张图片

        使用如上的方法,成功将文件中的字符给打印出来。 

        实现将test.txt文件中的数据拷贝到data.txt中去(先将test.txt中放入很多的数据),如下代码操作:

文件操作(C/C++)_第12张图片

        利用此操作,成功的将test.txt中的数据全拷贝到了新的文件中去。 

5.2 fgetc和fputs函数 

        这两个函数和以上两个函数很相似,不过区别在上面两个函数读写一个字符,而这两个函数读写字符串。同样的,fgets函数为文本输入函数,适用于所有的输入流,fputs函数为文本输出函数,适用于所有的输出流。

对于fputs函数的使用:

         该函数传入的第一个参数为字符串,第二个参数为文件指针,返回类型为int,具体的使用如下:

文件操作(C/C++)_第13张图片

        该操作将字符串dagsd写入到了文件中。 

        对于fgets该函数的操作:

文件操作(C/C++)_第14张图片

        对于以上的fgets函数,需要传入三个参数,其中第一个参数为字符指针,第二个为需要读取字符的数量,第三个为文件指针,返回类型为char*,对于以上函数的使用如下:

文件操作(C/C++)_第15张图片         如上图所示,将文件中的前五个字符读入了arr数组中,然后还会在后面加上一个’/0‘。对于以上的操作,我们大多都是以文件为流的形式进行距离,实际上我们也可以通过标准流进行输入输出,如下:

文件操作(C/C++)_第16张图片

        如上图所示,可以由我们输入之后在输出。 

5.3 fprintf和fscanf函数

        对于这两个函数,其中fprintf的功能为格式化输出函数,fscanf为格式化输入函数,这两个函数都适用于所有的输入流输出流。具体的用法如下:

        对于fprintf函数:

文件操作(C/C++)_第17张图片

        如上图对比,fprintf的参数相对于printf仅仅多了一个文件指针变量,所以相对于fprintf的使用,我们只需要参照平时对printf函数的使用,在前面加一个文件指针。所以具体的用法如下:

文件操作(C/C++)_第18张图片

        通过以上就便于将一些结构体类型的数据写到文件中去。

        对于fscanf函数,如下:

文件操作(C/C++)_第19张图片

        同以上的fprintf一样,相对于fscanf与scanf的区别仅仅只在比scanf多一个文件指针参数, 对于fscanf的使用如下:

文件操作(C/C++)_第20张图片

        如上图所以,可以成功的将文件中的数据写入到新的变量之中,然后将其输出出来。 

5.4 fwrite和fread函数

        这两个文件函数相对于以上三对函数有着很大的区别,这两个函数为二进制输入输出函数,仅仅适用于文件输入输出流,fread为二进制输入,fwrite为二进制输出函数。

        对于fwrite函数:

文件操作(C/C++)_第21张图片

         这个函数是直接将一个数据块写入到文件中去,其中第一个参数为要写数据块的首地址,第二个参数表示这个数据块所占的细节,第三个参数表示要写入多少个这样的数据块,最后一个就是一个文件指针变量。具体用法举例如下:

文件操作(C/C++)_第22张图片

        如上图所示对于fwrite函数的用法,对于该函数,因为是二进制,所以在读写的时候使用“wb”,“rb”。对于打开的文件中为什么是乱码的形式,是因为二进制文件在文本文件中的不能正确的显示。

        对于fread函数:

文件操作(C/C++)_第23张图片

        该函数的作用是把文件中的数据写count个,每个元素的大小为size,然后写道指针ptr指向的地址处,以上的四个参数与fwrite的四个参数一样。

文件操作(C/C++)_第24张图片

         如上的操作,我们将文件中的数据写到stu2变量中。

6.随机读写

        对于随机读写,一共包含三个函数:fseek、ftell、rewind

6.1 fseek函数

        该函数的作用是根据文件指针的位置和偏移量来定位文件指针,具体的解释如下:

        对于该函数,传入的参数第一个为文件指针,第二个为偏移量,第三个为起始位置,即就是根据相对于起始位置的偏移量来移动文件指针,对于起始位置:

文件操作(C/C++)_第25张图片

        一共有三种选择,SEEK_SET为文件指针当前位置,SEEK_CUR为文件指针当前位置,SEEK_END为文件指针的末尾位置。具体的使用方法如下,先将test.txt中的内容改为abcdef。

文件操作(C/C++)_第26张图片

        以上就为通过feek来修改文件指针所指向的位置。

6.2 ftell函数

        ftell函数的作用为返回当前文件指针相对于起始位置的偏移量。

        该函数的仅仅只需要传入文件指针即可,使用较为简单,如下:

文件操作(C/C++)_第27张图片

        以上就为ftell函数的使用。

 6.3 rewind函数

        rewind函数的作用为将文件指针的位置回到文件的起始位置。

        仍然只需要传入文件指针为参数。

        简单用法举例: 

文件操作(C/C++)_第28张图片

7.文件读取结束的判定

        在文件的读取中,有时对于文件的结束,可能出于一些其他的原因,但是最后也并未自动显示出来,所以我们需要使用相对应的函数,来判断函数结束的原因。

        feof函数:当文件读取结束的时候,用来判断读取结束的原因是否是:遇到文件末尾而结束。

        ferror函数:用于判断文件读取结束时,是否是因为错误而结束的。 

        对于文本文件读取是否结束,我们需要判断返回值是否为EOF或者NULL,fgetc判断为EOF,fgets函数判断为NULL。

        二进制文件读取是否结束,判断返回值是否小于实际要读的个数,如:fread判断返回值是否小于实际要读取的个数,具体的应用实例如下:

        对于文本文件:

文件操作(C/C++)_第29张图片

        对于二进制文件:

文件操作(C/C++)_第30张图片

        以上的这两段代码就是对文件读取结束时的判定的应用。 

你可能感兴趣的:(c语言,c++,开发语言)