C语言文件操作的介绍

目录

前言:

开始:

fopen函数和 fclose函数

fopen() 打开一个文件

fclose() 关闭一个文件

四组 读取,写入 函数介绍:

1.fgetc()和fputc()

fputc()把一个字符写入文件中

fgetc()从文件中读取一个字符

2.fscanf() 和 fprintf()

fprintf()把格式化信息写入到文件中

fscanf()从文件中读取格式化信息

3.fgets()和fputs()

fputs()把一行字符串信息写入文件中

fgets()从文件中读取一行字符串信息

4.fread()和 fwrite()

fwrite()把 数组信息写入文件中,数组类型未定义,可以是int、也可以是char

fread()从文件中读取 数组信息,数组信息可以是int、也可以是char

fseek函数和ftell函数

fseek()移动文件中光标的位置,来调整写入或读取信息的位置

ftell()告诉你现在文件光标离 文件源头位置 的偏移量

结束:


前言:

1.本文章只介绍文件操作的函数基本概念和基本操作,对于二进制文件和ASCII码文件(也是文本文件)这里不做介绍,对于“流”的概念也不做介绍。

2.首先我们会来学习打开文件和关闭文件,这两个操作是最最基本的操作,这里会介绍 fopen 函数和 fclose 函数。

3.接着我们会来介绍文件 写入读取 操作。这里有四组函数需要大家来辨析:

        a. fgetc 和 fputc ;

        b. fscanf 和 fprintf ;

        c. fgets 和 fputs ;

        d. fread 和 fwrite ;  //注意:这组函数用于二进制文件中

4.最后我们来讲一下 ftell 函数 和 fseek 函数。

5.总结该文章内容需要具有一点初级文件操作知识,但笔者尽力让大家都能学会操作,但内容和原
理还需要大家再去其他地方了解什么是“流”,什么是 二进制 文件和 ASCII码(文本) 文件。


开始:

fopen函数和 fclose函数

fopen() 打开一个文件



1. FILE * 是文件指针;
2. const char * filename 是要打开文件的名称,文件名也是文件标识。文件标识的组成为:
        文件路径 + 文件名主干 + 文件后缀
      这个常规打开方式有两种情况:
        a.直接在代码文件所在的目录下寻找该文本。直接输入文件名,但这种方式只能适用于放在和代码文件一个路径的文件,如下图,红色一号所标记的位置就是代码文件,红色二号所标记的位置就是文本文件,也就是我们打开的文本文件。
        b.直接输入文件的绝对路径,会根据路径一直找到你想要打开的文件。

3. const char * mode 的意思是选择你需要选择的模式,是“只读”文本,还是“只写”文本等。
        以下附上打开文本的几种模式:

⽂件使⽤⽅式
含义
如果指定⽂件不存在
“ r ”(只读)
为了输⼊数据,打开⼀个已经存在的⽂本⽂件
出错
“ w ”(只写)
为了输出数据,打开⼀个⽂本⽂件
建⽴⼀个新的⽂件
“ a ”(追加)
向⽂本⽂件尾添加数据
建⽴⼀个新的⽂件
“ rb ”(只读)
为了输⼊数据,打开⼀个⼆进制⽂件
出错
“ wb ”(只写)
为了输出数据,打开⼀个⼆进制⽂件
建⽴⼀个新的⽂件
“ ab ”(追加)
向⼀个⼆进制⽂件尾添加数据
建⽴⼀个新的⽂件
“ r+ ”(读写)
为了读和写,打开⼀个⽂本⽂件
出错
“ w+ ”(读写)
为了读和写,建立⼀个新的⽂件
建⽴⼀个新的⽂件
“ a+ ”(读写)
打开⼀个⽂件,在⽂件尾进⾏读写
建⽴⼀个新的⽂件
“ rb+ ”(读写)
为了读和写打开⼀个⼆进制⽂件
出错
“ wb+ ”(读写)
为了读和写,新建⼀个新的⼆进制⽂件
建⽴⼀个新的⽂件
“ ab+ ”(读写)
打开⼀个⼆进制⽂件,在⽂件尾进⾏读和写
建⽴⼀个新的⽂件

基本的模式就是" r "," w "," a "," rb "," wb "," ab "加上了字符"b"代表的是打开二进制文本。

不难发现只要是打开模式为 r加什么的,如 r 、r+ 、rb 、rb+ 模式,只要先前不存在该文件都会出错。

fclose() 关闭一个文件

fclose 函数相对简单,只需要输入文件指针,就算关闭文件了。

如图即可:

关闭文件后,让文件指针 fp 置空是一种习惯。


四组 读取,写入 函数介绍:

1.fgetc()和fputc()

fputc()把一个字符写入文件中

        首先还是介绍函数原型:

        I.写入成功就会返回该字符的值,写入失败就会返回 EOF

        II. int character 是要放入的字符,char 类型也是 int 类型家族的,字符都有对应的ASCII码值。

        III. FILE * stream 是要写入的文件指针。写入的位置根据文件光标的移动,写入一个字符,光标会往后移动一个位置。

        打开文件 " w ",关闭文件 (为什么用w模式,因为我要用一个新的文本来演示):

根据上面的代码可以基本懂得了fputc()的运用,使用方法就是:

fputc(你要放入的字符,要放入的文件指针)

fgetc()从文件中读取一个字符

        I.读取成功就返回读取到的字符,读取失败就会返回 EOF 。

        II. FILE * stream 是要读取的文件指针。

根据上一个代码进行改动,尝试 fgetc() 的功能(打开文件 " r ",关闭文件)。

重新以只读模式打开文件,然后用 fgetc() 来一一读取字符,使用方法:

char ch = fgetc(要读取的文件指针)

拿一个变量ch来接收读取到的字符。

现在读者可以就这一组读取、写入函数来做简单的尝试了

2.fscanf() 和 fprintf()

fprintf()把格式化信息写入到文件中

        I.写入成功会返回 写入成功的 字符个数。

        II.FILE * stream 是要写入的文件指针。

        III. const char *format 是可变参数列表。与原printf对比如下(只是多了一个写入的地方):

而且fprintf 函数可以用来输入格式化信息,如下图(打开文件" w ",关闭文件):

正常的像printf一样写入你要写入的信息,在写入的信息前加上要写入的地方-- fp 

写入信息后就知道为什么说是格式化信息了,因为文本存放的内容都有一定的格式。

相对应的 ,我们就有fscanf来读取信息(并不是说只能用fscanf来读取格式化信息,其他信息也可以读取,只是格式化信息更方便),当然这个fscanf也可以像上面的fprintf来理解,依旧是在scanf的基础上加个读取的位置。

需要注意的是,我们想给内容换行时,需要自己在fprintf函数里面加上对应的换行符,这样在文本上面也会显示换行,如果自己不输入,内容就会连在一起,因为内容都是自己输入的,我们自己不给内容加格式,内容就会连在一起写入文件,如下:

fscanf()从文件中读取格式化信息

        I.写入成功会返回 读取成功的 字符个数,读取失败会返回 EOF 。

        II.FILE * stream 是要读取的文件指针。

        III. const char *format 是可变参数列表。与原scanf对比如下(只是多了一个读取的地方):

尝试一下使用 fscanf 函数(打开文件" r ",关闭文件):

接下来,这组函数读者们也可以尝试一下了

3.fgets()和fputs()

fputs()把一行字符串信息写入文件中

        I. 返回值:

        II. const char * str 是要写入的文件的字符串。例如:"hello world!"

        III. FILE * stream 是要写入的文件指针。

现在来看看puts函数:

        发现两者的区别在于参数里面,fputs函数多出了 FILE * stream 这个参数,这个参数就是字符数组要出现的地方。在fputs函数中,字符串出现在文件指针所指向的文件中;而puts函数中,字符串会显示在调试控制台上。

现在来尝试一下这个函数(打开文件" w ",关闭文件):

可以看到,要使用fputs函数,就需要我们现有一个字符数组去储存我们需要的信息,再通过fputs函数来写入文件中。

接下来是fgets函数:

fgets()从文件中读取一行字符串信息

        I. 返回值:

        II. char * str 是读取到的字符串要存放到str所指向的空间。通俗易懂就是,你要先创造一个字符数组,然后用这个新建字符数组来保存从文本文件中读取到的字符串。

        III. int num 是读取字符的最大数目。这个是用来保证 char * str 不会越界访问。联合上面所说的新建的字符数组是有长度限制的,fgets保证你输入了num后,只读取num个字符。需要注意的是,只能读取到num-1个字符,因为数组最后一个位置要留来存放' \0 '

        IV. FILE * stream 是所读取的文件指针。

尝试一下这个fgets函数(文件打开" w ",文件关闭):

        我们发现我们读取成功了。也许细心的读者发现了一个问题,就是为什么我们在调试控制台的内容会换行呢,明明在printf函数上并没有写出换行符。

        哈哈,读者可以想起来我们使用fputs函数的时候给文本内容添加了换行符,因为我们想让内容更美观。

那么是不是tmp数组读取到了这个换行符呢?我们可以用VS2022来调试看看,是否真的读取到了换行符:

看来真的是读取到了。

到读者们尝试一下fgets函数和fputs函数了

4.fread()和 fwrite()

fwrite()把 数组信息写入文件中,数组类型未定义,可以是int、也可以是char

        I. 返回值:这里笔者不讨论返回值,想了解的读者可以自行浏览cplusplus网站来获取相关知识。

        II. const void * ptr 这里的无类型指针,方便后面内容的写入,因为有可能写入的是 char 类型数据,也有可能 int 类型数据 。而且这个写入的内容也是需要我们自己先创造一个数组类型来记录我们的内容,然后这就是我们的 ptr ,再把这个数组的内容写入二进制文件中。

        III. size_t size 指的是写入的每一个数据的大小,如果写入的是int类型数据,这里就是4,如果是char类型数据,这里就是1。

        IV. size_t count 指的是要写入多少个数据。在上一个参数确定好后,再确定我们要写入多少个这样大小的数据。

        V. FILE * stream 指的是要写入的文件指针。

现在我们来尝试一下这个函数(打开文件" wb ",注意此时用的是二进制写入,关闭文件):

你会发现记事本不能完全解析二进制文本,只能查看ABCDEFG,但是我们放入的{1,2,3,4,5,6}都不能直接查看,我们可以用VS2022自带的二进制编译器查看一下:

我们会发现确实存到文本里面去了。

接下来到fread函数:

fread()从文件中读取 数组信息,数组信息可以是int、也可以是char

这个函数的参数表和fwrite函数的一模一样,用法也是一样的

        I. 返回值:想了解的读者可以自行浏览cplusplus网站来获取相关知识。

        II. const void * ptr 这里的无类型指针,方便后面内容的读取。因为有可能读取的是 char 类型数据,也有可能 int 类型数据 。而且这个读取获得的内容存放也是需要我们自己先创造一个数组类型来记录我们的内容,然后这就是我们的 ptr ,再从二进制文件中读取内容存放到我们创造的数组中。

        III. size_t size 指的是写入的每一个数据的大小,如果写入的是int类型数据,这里就是4,如果是char类型数据,这里就是1。

        IV. size_t count 指的是要写入多少个数据。在上一个参数确定好后,再确定我们要写入多少个这样大小的数据。

那我们直接来体验一下这个函数吧:

在上面的体验中,我们读取还是需要小心,因为如果在第一个fread中没有控制好读取的个数,会导致tmp1字符数组会读取到我们的int类型的数据,然后导致读取的内容混乱。

OK,这四组函数我们都已经体验了一遍,请读者们好好辨析一下这四组读取、写入函数的不同吧,或者说是体会他们之间微妙的用法,怎么样的数据方式需要哪一组函数会更加好。


fseek函数和ftell函数

fseek()移动文件中光标的位置,来调整写入或读取信息的位置

        I.返回值:

        II. FILE * stream 是要移动的文件指针。

        III. long int offset 是以原点(origin)移动的偏移量,可以是0,也可以是正数、负数。

        IV. int origin 是原点,该函数给出了三个原点位置:

我们可以来分两个方向来尝试一下该函数,一个是正常移动的情况,一个是非正常移动的情况:

非正常的移动:

去掉if else 语句后(还是读取成功了,光标没有移动):

那么如果移动的偏移量大于文件的字符数呢(就是文件没有100的位置来偏移,但是我就是要从文件的开头(SEEK_SET)偏移一百个单位)?这个留给读者来体验一下了。

还有一个问题读者可能想问了,那么我怎么知道我现在的光标移动到哪里了。

接下来,ftell函数会告诉你它走到哪了

ftell()告诉你现在文件光标离 文件源头位置 的偏移量

        I. 返回值:

        II. FILE * stream 是要访问的 文件指针。

那么我们还是来试试吧:

发现确实是可以返回当前光标所处的位置。

那么到这里,文章就算结束了,希望看过文章的读者们多多练习,熟能生巧,但也要记得劳逸结合!!

结束:

谢谢各位的浏览,同时感谢比特鹏哥激励笔者去动手写博客!!

  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值