一、初识文件
1、什么是文件?
如图
文件就是存储在外部存储器上的数据集合 / 字符或字节序列。
2、文件命名(三要素)
(1)文件路径:表示文件在外部存储设备中的位置
(2)文件主干
(3)文件后缀:一般不超过3个字符(表示文件的类型:如:.txt .xls)
比如:D:\CC\biji\file.dat 表示:file.dat文件存放在D盘中的CC目录下的biji子目录下面。
二、文件分类
1、广义文件分类
从操作系统的角度来看,可分为普通文件和设备文件。
普通文件 | 驻留在磁盘或其他外部介质的一个有序数据集 |
设备文件 | 与主机相连的各种外部设备,如显示器、打印机、键盘等。 |
注释:设备只是逻辑上的文件,操作系统把各种设备都统一作为文件处理。(比如:键盘被定义为标准输入文件,在键盘上键入数据就意味着从标准输入文件接收数据。)
2、程序设计中的文件类型
(1)程序文件(内容为程序代码)
源程序文件 | 后缀为.c |
目标文件 | 后缀为.obj |
可执行文件 | 后缀为.exe |
(2)数据文件(内容是供程序运行时读写的数据,比较多样)
按照存储方式的不同分为:
文本文件(ASCII文件) | 每一个字节放一个ASCII码 |
二进制文件 | 数据在内存中是以二进制形式存储的,如果不加转换地输出到外存,就是二进制文件。(节省不必要的转换时间) |
注释:
【1】字符数据一律以ASCII形式存储 / 数值型数据既可以以ASCII形式存储(容易展示)也可以以二进制形式(节省空间)存储。
【2】程序要使用文本文件中存储的数据计算,就需要把字符流转成二进制流。
三、文件类型指针
一、解释
1、文件类型指针 指向 被使用的文件在内存中开辟的一个相应的文件信息区(该信息区用来存放文件的有关信息,如文件名,文件状态及文件当前位置……)。
2、这些信息是保存在结构体变量中的。该结构体类型由系统声明(声明信息在头文件"stdio.h"中),取名为FILE,相应的指针类型为FILE *。
二、使用
一般设置一个指向FILE类型变量的指针变量,然后通过按它来引用这些FILE类型变量。
FILE f1,f2,*fp1=&f1,*fp2=&f2;
四、文件操作
1、打开文件
fopen()函数
[1]调用方式:fopen(文件名,打开文件的方式);
eg:fopen("D:\CC\biji\file.dat","r"); //表示以只读方式打开文件 D:\CC\biji\file.dat
注:当打开的文件和执行程序在同一个目录中时,文件名的路径可以省略,如:fopen("a1","r");
[2]返回值:指向被打开文件的指针。
[3]使用方式:将fopen的返回值赋给一个指向文件的指针变量。
eg:
*打开文件方式的字符FILE *fp; fp=fopen("a1","r");
r(只读) 为了输入数据,打开一个已经存在的文本文件 w(只写) 为了输出数据,打开一个文本文件, a(追加) 往一个文件末尾添加新的数据 b 二进制文件 t 文本文件 + 读和写 某些字符可以组合,如”rb"表示读一个二进制文件。特别注意"+"这种打开方式
r+ 要求文件已存在 w+ 新建一个文件(先写后读) a+ 既可以输入也可以输出数据
(用a+方式打开的文件,原来的内容不被删去,文件读写位置标记移到文件末尾,可以添加也可以读)
[4]注意事项:如果文件打开失败,fopen将会返回一个空指针NULL。为了避免文件打开失败,常用if(fp==NULL)判断操作是否成功。
if(fp=fopen("file1","r")==NULL); { printf("cannot open this file\n"); exit(0); }
2、数据读取
(1)读字符
fgetc()函数
[1]使用
char c; c=fgetc(fp);
读取成功返回所读字符,失败返回EOF(-1)。
[2]理解:
[3]应用 :读取整个文件内容/读取多行文本
while(!feof(fp)) { c=fgetc(fp); putchar(c); }
[4]注意:
*使用fgetc读取的文件,必须以r/w的方式打开
*特别的:可用来移动指针,不让返回值赋值(了解)
(2)读字符串
fgets()函数
[1]声明
fgets(str,n,fp);//从fp指向的文件读入长度为 n-1(加末尾的'\0')的字符串,放到字符数组str中。读成功返回地址str,失败返回NULL。
[2]说明:
*fgets()函数中第一个参数可以是静态定义的字符数组,也可以是动态分配的字符数组。(作为参数,只写数组名就行,若写的是str[i]则说明str是二维数组。)
*第二个参数是字符串实际长度+1,因为还有末尾的'\0'。
(3)用格式化的方式读文本文件
fscanf()函数
[1]调用方式:
fscanf(文件指针,格式字符串,&输入列表);
eg:fscanf(fp,"%d",&i);
[2]优缺点:
*可以把各种类型的数据写入文本文件
*效率低(因为输入时ASCII码字符要转化为二进制保存)
(4)用二进制方式读二进制文件
fread()函数
[1]调用形式:
int n; n=fread(buffer,size,count,fp); //buffer:指向数据内存区域的指针。即“读入/输出”数据在内存中的起始地址 //size:要进行读或写的每个数据项的字节数 //count:多少个size字节的数据项
[2]注意:
执行时,文件位置指针会随着数据的读取而向后移动。执行结束,返回实际读出的元素个数(不一定等于设置的count)。
3、数据写入
(1)写字符
fputc()函数
[1]使用
fputc('c',fp);//把字符c写到fp所指的文件中
[2]注意
*被写入的文件:可以以"r","w","a"方式打开
*如需保留原有文件,必须以追加方式打开文件。
*若被写入的文件不存在,则创建该文件。
(2)写字符串
fputs()函数
[1]声明
fputs(str,fp);//将str指向的字符串写到fp所指的文件中。成功返回0,失败返回非0数字。
eg:fputs("china",fp);
[2]注意
*第一个参数可以是字符串常量、字符串数组、字符型指针。
*字符串末尾的'\0'不输出。
(3)用格式化的方式写文本文件
fprintf()函数
[1]调用方式:
fprintf(文件指针,格式字符串,输出列表);
eg:fprintf(fp,"%d,%.3f",i,f);
[2]缺点:效率低(输出时二进制转化为字符输出)。
(4)用二进制方式写二进制文件
fwrite()函数
[1]调用形式:
int n; n=fwrite(buffer,size,count,fp); //buffer:指向数据内存区域的指针。即“读入/输出”数据在内存中的起始地址 //size:要进行读或写的每个数据项的字节数 //count:多少个size字节的数据项
表示从buffer所指的内存中取出长度为count个size字节的数据元素项,写入fp所指文件中。
[2]注意:
*执行结束,返回成功写入读入数据元素个数。
4、关闭文件
即撤销文件信息区/缓冲区,撤销成功返回0,撤销失败返回EOF(-1);
如果不关闭文件,会造成数据丢失。
fclose()函数
[1]调用方式:fclose(文件指针);
eg:fclose(fp);