文件与文件操作

1.文件

1.1文件的类型

为了防止数据的丢失,我们想对数据进行持久化的保存,文件也就出现了,例如我们写的代码就会以文件的形式保存在电脑中,下次打开时就不会丢失写出来的代码。

在程序设计中,一般从文件功能的角度对文件进行分类:程序文件和数据文件。

首先是程序文件,例如我们以.c为后缀保存的文件就是程序文件,程序文件包括源程序文件,目标程序文件和可执行程序文件。

其次是数据文件,程序在运行过程中需要输入数据和输出内容到文件上,这样的文件就是数据文件。例如,我们在敲代码时把数据直接打印在屏幕上,那么数据并没有被保存起来,只能通过再次运行程序才能知道数据,但是如果把数据输出到文件上,就可以直接通过文件了解到程序运行的结果。而下面要讲到的文件操作也指数据文件。

而文件名由三个部分组成:文件路径+文件名主干+文件后缀

例如:C:\user\test.txt

C:\user\  就是文件的路径

test         就是文件名主干

.txt          就是文件后缀

1.2二进制文件与文本文件

由于数据可以以二进制的形式直接储存在外部文件中,也可以转换成ASCII码的形式储存,数据文件也可以分为二进制文件和文本文件,以ASCII码的形式储存在硬盘中的文件就是文本文件。

字符数据一律以ASCII码的形式储存,而数值型的数据则二进制和ASCII码都可,因此在以二进制文件保存的.txt文件中,我们可以正常看到字母,但是对于数值通常只能看到乱码。

1.3文件指针

首先,需要了解流的概念

程序在运行时,需要接触到各种输入和输出操作,例如,输入可以通过键盘输入,也可以通过文件输入数据,输出可以直接在电脑屏幕上输出,也可以输出到文件中。那么就将各种数据的输入输出抽象成了流这个概念。

标准流的概念也就应运而生,

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

stdout-标准输出流,大多数输出环境是输出到电脑屏幕上,printf函数就是将数据输出到标准输出流中。

stderr-标准错误流,大多数环境中输出至显示屏。

而这三个流的类型就是FILE*,也就是文件指针,C语言程序在启动时会默认打开这三个标准流,因此我们可以直接使用printf、scanf函数对标准流进行操作。但是,当我们想从文件中获取数据时,就需要自己通过文件指针打开文件进行关于流的各种操作。

文件在被使用时,系统会根据文件的情况创建一个FILE结构的变量,并填充其中的信息,文件指针就用来指向这片区域,因此,我们可以通过文件指针来操作文件。

2.文件操作

2.1文件的打开和关闭

我们已经知道,可以通过文件指针来指向打开文件开辟的空间,那么我们可以通过以下方式打开文件

FILE * fopen( const char * filename, const char * mode);//打开文件
int fclose( FILE * stream);//关闭文件

其中,打开文件有不同的模式,也就是fopen函数第二的参数的作用,下面进行简单的介绍:

mode含义如果指定文件不存在
r为输入数据,打开一个已存在的文本文件出错
w为输出数据,打开一个文本文件建立一个新文件
a向文本文件末尾添加数据建立一个新文件
rb为输入数据,打开一个二进制文件出错
wb为输出数据,打开一个二进制文件建立一个新文件
ab向二进制文件末尾添加数据建立一个新文件
r+为读和写,打开一个文本文件出错
w+为读和写,新建一个文本文件建立一个新文件
a+打开一个文本文件,在文件末尾进行读和写建立一个新文件
rb+为读和写,打开一个二进制文件出错
wb+为读和写,新建一个二进制文件建立一个新文件
ab+打开一个二进制文件,在文件末尾进行读和写建立一个新文件

 以下举一个实例帮助更好理解:

#include <stdio.h>
int main()
{
    FILE* pf = fopen("test.txt","w");//打开文件
    if(pf != NULL)
    {
        fputs("fopen example",pf);//文件操作(fputs函数后面会讲)
        fclose(pf);//关闭文件
        pf = NULL;//避免野指针的出现
    }
    return 0;
}

2.2文件的顺序读写

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

 文件的顺序读写涉及到以上函数,我们取fgets函数和fputs函数为例子进行讲解:

首先是fgets函数

char * fgets ( char * str, int num, FILE * stream )

函数有三个参数,第一个是一个字符数组的指针,函数会把从文件中读取到的字符串放到该数组中,第二个是要复制的字符数,第三个是文件的文件指针 。

需要注意的是,函数会在字符串末尾放上\0,所以其实复制过来的字符数只有num-1个。

然后是fputs函数

int fputs ( const char * str, FILE * stream )

函数有两个参数,第一个是要放入文件中的字符串,第二个则是文件的文件指针

需要注意的是,函数在文件中是不会自动换行的,也就是用两次该函数,前后两个字符串会直接连在一起。

2.3文件的随机读写

有时候,我们在读写文件时并不一定是从文件开头开始的,这时候我们需要用到fseek、ftell和rewind函数。

fseek函数可以用来把文件指针移动到我们想要的地方,例如:

文件中有如下字符串:abcdefg

在我们使用一次fgetc函数以后读取到字符'a',再使用fgetc函数读取到的字符就是'b',文件指针就发生了偏移。fseek函数就可以操作文件指针,比如我们想读取字母d,由于操作过两次文件光标,此时,我们输入

fseek(FILE* stream, 1, SEEK_CUR);

然后再使用fgets函数,就能得到字母d。对于fseek函数的三个参数,第一个参数是文件指针,第二个是要指针偏移的量,第三个有三种选择,SEEK_SET是从文件开始的地方开始偏移,SEEK_CUR是从文件指针当前指向的位置开始偏移,SEEK_END是从文件结束的地方开始偏移。

有的时候我们会记不清文件指针到哪了,ftell函数就能告诉我们现在文件指针相对于起始位置的偏移量,rewind函数则是把文件指针挪到文件的启示位置。两个函数都只有一个参数,也就是文件指针。

2.4文件读取结束

我们想要判断文件读取是否结束时,不能直接使用feof函数,该函数只能判断文件读取结束的原因是否是遇到文件尾结束。

如果是文本文件,可以通过fgetc判断是否是EOF,或者fgets判断返回值是否是NULL。

如果是二进制文件,则判断返回值是否小于实际要读的个数,例如使用fread函数。

2.5文件缓冲区

在输入和输出数据时,C语言会先将数据放入文件缓冲区,然后再转移到文件中或程序变量中,因此我们需要刷新文件缓存区或文件操作结束时关闭文件,这样才能避免数据丢失等问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值